From e2f8b407a7b030aa8cfc7eb3867cbe779ed0f27b Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Tue, 7 May 2019 15:46:08 -0700 Subject: [PATCH] Add lorax 29.28 documentation --- f29-branch/.buildinfo | 4 + f29-branch/.doctrees/composer-cli.doctree | Bin 0 -> 42707 bytes f29-branch/.doctrees/composer.cli.doctree | Bin 0 -> 253746 bytes f29-branch/.doctrees/composer.doctree | Bin 0 -> 63427 bytes f29-branch/.doctrees/environment.pickle | Bin 0 -> 2277347 bytes f29-branch/.doctrees/index.doctree | Bin 0 -> 6432 bytes f29-branch/.doctrees/intro.doctree | Bin 0 -> 9111 bytes .../.doctrees/livemedia-creator.doctree | Bin 0 -> 168643 bytes f29-branch/.doctrees/lorax-composer.doctree | Bin 0 -> 112474 bytes f29-branch/.doctrees/lorax.doctree | Bin 0 -> 70335 bytes f29-branch/.doctrees/modules.doctree | Bin 0 -> 2526 bytes f29-branch/.doctrees/product-images.doctree | Bin 0 -> 7055 bytes f29-branch/.doctrees/pylorax.api.doctree | Bin 0 -> 732127 bytes f29-branch/.doctrees/pylorax.doctree | Bin 0 -> 542323 bytes f29-branch/README | 5 + f29-branch/_modules/composer/cli.html | 271 + .../_modules/composer/cli/blueprints.html | 728 ++ f29-branch/_modules/composer/cli/cmdline.html | 267 + f29-branch/_modules/composer/cli/compose.html | 731 ++ f29-branch/_modules/composer/cli/modules.html | 265 + .../_modules/composer/cli/projects.html | 327 + f29-branch/_modules/composer/cli/sources.html | 369 + f29-branch/_modules/composer/cli/status.html | 273 + .../_modules/composer/cli/utilities.html | 312 + f29-branch/_modules/composer/http_client.html | 475 + f29-branch/_modules/composer/unix_socket.html | 276 + f29-branch/_modules/index.html | 257 + f29-branch/_modules/pylorax.html | 679 + f29-branch/_modules/pylorax/api/bisect.html | 266 + .../_modules/pylorax/api/checkparams.html | 261 + f29-branch/_modules/pylorax/api/cmdline.html | 280 + f29-branch/_modules/pylorax/api/compose.html | 1422 +++ f29-branch/_modules/pylorax/api/config.html | 355 + .../_modules/pylorax/api/crossdomain.html | 281 + f29-branch/_modules/pylorax/api/dnfbase.html | 398 + f29-branch/_modules/pylorax/api/gitrpm.html | 438 + f29-branch/_modules/pylorax/api/projects.html | 800 ++ f29-branch/_modules/pylorax/api/queue.html | 892 ++ f29-branch/_modules/pylorax/api/recipes.html | 1236 ++ f29-branch/_modules/pylorax/api/server.html | 299 + .../_modules/pylorax/api/timestamp.html | 268 + f29-branch/_modules/pylorax/api/v0.html | 2303 ++++ .../_modules/pylorax/api/workspace.html | 316 + f29-branch/_modules/pylorax/base.html | 284 + f29-branch/_modules/pylorax/buildstamp.html | 283 + f29-branch/_modules/pylorax/cmdline.html | 532 + f29-branch/_modules/pylorax/creator.html | 994 ++ f29-branch/_modules/pylorax/decorators.html | 247 + f29-branch/_modules/pylorax/discinfo.html | 262 + f29-branch/_modules/pylorax/dnfbase.html | 402 + f29-branch/_modules/pylorax/dnfhelper.html | 327 + f29-branch/_modules/pylorax/executils.html | 566 + f29-branch/_modules/pylorax/imgutils.html | 771 ++ f29-branch/_modules/pylorax/installer.html | 883 ++ f29-branch/_modules/pylorax/ltmpl.html | 1104 ++ f29-branch/_modules/pylorax/monitor.html | 420 + f29-branch/_modules/pylorax/mount.html | 319 + f29-branch/_modules/pylorax/sysutils.html | 349 + f29-branch/_modules/pylorax/treebuilder.html | 628 + f29-branch/_modules/pylorax/treeinfo.html | 280 + f29-branch/_sources/composer-cli.rst.txt | 63 + f29-branch/_sources/composer.cli.rst.txt | 86 + f29-branch/_sources/composer.rst.txt | 37 + f29-branch/_sources/index.rst.txt | 34 + f29-branch/_sources/intro.rst.txt | 67 + f29-branch/_sources/livemedia-creator.rst.txt | 657 + f29-branch/_sources/lorax-composer.rst.txt | 504 + f29-branch/_sources/lorax.rst.txt | 152 + f29-branch/_sources/modules.rst.txt | 8 + f29-branch/_sources/product-images.rst.txt | 27 + f29-branch/_sources/pylorax.api.rst.txt | 150 + f29-branch/_sources/pylorax.rst.txt | 165 + f29-branch/_static/ajax-loader.gif | Bin 0 -> 673 bytes f29-branch/_static/basic.css | 665 + f29-branch/_static/comment-bright.png | Bin 0 -> 756 bytes f29-branch/_static/comment-close.png | Bin 0 -> 829 bytes f29-branch/_static/comment.png | Bin 0 -> 641 bytes f29-branch/_static/css/badge_only.css | 1 + f29-branch/_static/css/theme.css | 6 + f29-branch/_static/doctools.js | 313 + f29-branch/_static/documentation_options.js | 9 + f29-branch/_static/down-pressed.png | Bin 0 -> 222 bytes f29-branch/_static/down.png | Bin 0 -> 202 bytes f29-branch/_static/file.png | Bin 0 -> 286 bytes f29-branch/_static/fonts/Inconsolata-Bold.ttf | Bin 0 -> 108360 bytes .../_static/fonts/Inconsolata-Regular.ttf | Bin 0 -> 95960 bytes f29-branch/_static/fonts/Lato-Bold.ttf | Bin 0 -> 657188 bytes f29-branch/_static/fonts/Lato-BoldItalic.ttf | Bin 0 -> 699008 bytes f29-branch/_static/fonts/Lato-Italic.ttf | Bin 0 -> 723544 bytes f29-branch/_static/fonts/Lato-Regular.ttf | Bin 0 -> 657212 bytes f29-branch/_static/fonts/Lato/lato-bold.eot | Bin 0 -> 256056 bytes f29-branch/_static/fonts/Lato/lato-bold.ttf | Bin 0 -> 657188 bytes f29-branch/_static/fonts/Lato/lato-bold.woff | Bin 0 -> 309728 bytes f29-branch/_static/fonts/Lato/lato-bold.woff2 | Bin 0 -> 184912 bytes .../_static/fonts/Lato/lato-bolditalic.eot | Bin 0 -> 266158 bytes .../_static/fonts/Lato/lato-bolditalic.ttf | Bin 0 -> 699008 bytes .../_static/fonts/Lato/lato-bolditalic.woff | Bin 0 -> 323344 bytes .../_static/fonts/Lato/lato-bolditalic.woff2 | Bin 0 -> 193308 bytes f29-branch/_static/fonts/Lato/lato-italic.eot | Bin 0 -> 268604 bytes f29-branch/_static/fonts/Lato/lato-italic.ttf | Bin 0 -> 723544 bytes .../_static/fonts/Lato/lato-italic.woff | Bin 0 -> 328412 bytes .../_static/fonts/Lato/lato-italic.woff2 | Bin 0 -> 195704 bytes .../_static/fonts/Lato/lato-regular.eot | Bin 0 -> 253461 bytes .../_static/fonts/Lato/lato-regular.ttf | Bin 0 -> 657212 bytes .../_static/fonts/Lato/lato-regular.woff | Bin 0 -> 309192 bytes .../_static/fonts/Lato/lato-regular.woff2 | Bin 0 -> 182708 bytes f29-branch/_static/fonts/RobotoSlab-Bold.ttf | Bin 0 -> 170616 bytes .../_static/fonts/RobotoSlab-Regular.ttf | Bin 0 -> 169064 bytes .../fonts/RobotoSlab/roboto-slab-v7-bold.eot | Bin 0 -> 79520 bytes .../fonts/RobotoSlab/roboto-slab-v7-bold.ttf | Bin 0 -> 170616 bytes .../fonts/RobotoSlab/roboto-slab-v7-bold.woff | Bin 0 -> 87624 bytes .../RobotoSlab/roboto-slab-v7-bold.woff2 | Bin 0 -> 67312 bytes .../RobotoSlab/roboto-slab-v7-regular.eot | Bin 0 -> 78331 bytes .../RobotoSlab/roboto-slab-v7-regular.ttf | Bin 0 -> 169064 bytes .../RobotoSlab/roboto-slab-v7-regular.woff | Bin 0 -> 86288 bytes .../RobotoSlab/roboto-slab-v7-regular.woff2 | Bin 0 -> 66444 bytes .../_static/fonts/fontawesome-webfont.eot | Bin 0 -> 165742 bytes .../_static/fonts/fontawesome-webfont.svg | 2671 ++++ .../_static/fonts/fontawesome-webfont.ttf | Bin 0 -> 165548 bytes .../_static/fonts/fontawesome-webfont.woff | Bin 0 -> 98024 bytes .../_static/fonts/fontawesome-webfont.woff2 | Bin 0 -> 77160 bytes f29-branch/_static/jquery-3.2.1.js | 10253 ++++++++++++++++ f29-branch/_static/jquery.js | 4 + f29-branch/_static/js/modernizr.min.js | 4 + f29-branch/_static/js/theme.js | 3 + f29-branch/_static/minus.png | Bin 0 -> 90 bytes f29-branch/_static/plus.png | Bin 0 -> 90 bytes f29-branch/_static/pygments.css | 69 + f29-branch/_static/searchtools.js | 761 ++ f29-branch/_static/underscore-1.3.1.js | 999 ++ f29-branch/_static/underscore.js | 31 + f29-branch/_static/up-pressed.png | Bin 0 -> 214 bytes f29-branch/_static/up.png | Bin 0 -> 203 bytes f29-branch/_static/websupport.js | 808 ++ f29-branch/composer-cli.html | 422 + f29-branch/composer.cli.html | 1228 ++ f29-branch/composer.html | 559 + f29-branch/genindex.html | 1368 +++ f29-branch/index.html | 255 + f29-branch/intro.html | 278 + f29-branch/livemedia-creator.html | 1226 ++ f29-branch/lorax-composer.html | 798 ++ f29-branch/lorax.html | 608 + f29-branch/modules.html | 310 + f29-branch/objects.inv | Bin 0 -> 3826 bytes f29-branch/product-images.html | 250 + f29-branch/py-modindex.html | 483 + f29-branch/pylorax.api.html | 4308 +++++++ f29-branch/pylorax.html | 2452 ++++ f29-branch/search.html | 234 + f29-branch/searchindex.js | 1 + 151 files changed, 57032 insertions(+) create mode 100644 f29-branch/.buildinfo create mode 100644 f29-branch/.doctrees/composer-cli.doctree create mode 100644 f29-branch/.doctrees/composer.cli.doctree create mode 100644 f29-branch/.doctrees/composer.doctree create mode 100644 f29-branch/.doctrees/environment.pickle create mode 100644 f29-branch/.doctrees/index.doctree create mode 100644 f29-branch/.doctrees/intro.doctree create mode 100644 f29-branch/.doctrees/livemedia-creator.doctree create mode 100644 f29-branch/.doctrees/lorax-composer.doctree create mode 100644 f29-branch/.doctrees/lorax.doctree create mode 100644 f29-branch/.doctrees/modules.doctree create mode 100644 f29-branch/.doctrees/product-images.doctree create mode 100644 f29-branch/.doctrees/pylorax.api.doctree create mode 100644 f29-branch/.doctrees/pylorax.doctree create mode 100644 f29-branch/README create mode 100644 f29-branch/_modules/composer/cli.html create mode 100644 f29-branch/_modules/composer/cli/blueprints.html create mode 100644 f29-branch/_modules/composer/cli/cmdline.html create mode 100644 f29-branch/_modules/composer/cli/compose.html create mode 100644 f29-branch/_modules/composer/cli/modules.html create mode 100644 f29-branch/_modules/composer/cli/projects.html create mode 100644 f29-branch/_modules/composer/cli/sources.html create mode 100644 f29-branch/_modules/composer/cli/status.html create mode 100644 f29-branch/_modules/composer/cli/utilities.html create mode 100644 f29-branch/_modules/composer/http_client.html create mode 100644 f29-branch/_modules/composer/unix_socket.html create mode 100644 f29-branch/_modules/index.html create mode 100644 f29-branch/_modules/pylorax.html create mode 100644 f29-branch/_modules/pylorax/api/bisect.html create mode 100644 f29-branch/_modules/pylorax/api/checkparams.html create mode 100644 f29-branch/_modules/pylorax/api/cmdline.html create mode 100644 f29-branch/_modules/pylorax/api/compose.html create mode 100644 f29-branch/_modules/pylorax/api/config.html create mode 100644 f29-branch/_modules/pylorax/api/crossdomain.html create mode 100644 f29-branch/_modules/pylorax/api/dnfbase.html create mode 100644 f29-branch/_modules/pylorax/api/gitrpm.html create mode 100644 f29-branch/_modules/pylorax/api/projects.html create mode 100644 f29-branch/_modules/pylorax/api/queue.html create mode 100644 f29-branch/_modules/pylorax/api/recipes.html create mode 100644 f29-branch/_modules/pylorax/api/server.html create mode 100644 f29-branch/_modules/pylorax/api/timestamp.html create mode 100644 f29-branch/_modules/pylorax/api/v0.html create mode 100644 f29-branch/_modules/pylorax/api/workspace.html create mode 100644 f29-branch/_modules/pylorax/base.html create mode 100644 f29-branch/_modules/pylorax/buildstamp.html create mode 100644 f29-branch/_modules/pylorax/cmdline.html create mode 100644 f29-branch/_modules/pylorax/creator.html create mode 100644 f29-branch/_modules/pylorax/decorators.html create mode 100644 f29-branch/_modules/pylorax/discinfo.html create mode 100644 f29-branch/_modules/pylorax/dnfbase.html create mode 100644 f29-branch/_modules/pylorax/dnfhelper.html create mode 100644 f29-branch/_modules/pylorax/executils.html create mode 100644 f29-branch/_modules/pylorax/imgutils.html create mode 100644 f29-branch/_modules/pylorax/installer.html create mode 100644 f29-branch/_modules/pylorax/ltmpl.html create mode 100644 f29-branch/_modules/pylorax/monitor.html create mode 100644 f29-branch/_modules/pylorax/mount.html create mode 100644 f29-branch/_modules/pylorax/sysutils.html create mode 100644 f29-branch/_modules/pylorax/treebuilder.html create mode 100644 f29-branch/_modules/pylorax/treeinfo.html create mode 100644 f29-branch/_sources/composer-cli.rst.txt create mode 100644 f29-branch/_sources/composer.cli.rst.txt create mode 100644 f29-branch/_sources/composer.rst.txt create mode 100644 f29-branch/_sources/index.rst.txt create mode 100644 f29-branch/_sources/intro.rst.txt create mode 100644 f29-branch/_sources/livemedia-creator.rst.txt create mode 100644 f29-branch/_sources/lorax-composer.rst.txt create mode 100644 f29-branch/_sources/lorax.rst.txt create mode 100644 f29-branch/_sources/modules.rst.txt create mode 100644 f29-branch/_sources/product-images.rst.txt create mode 100644 f29-branch/_sources/pylorax.api.rst.txt create mode 100644 f29-branch/_sources/pylorax.rst.txt create mode 100644 f29-branch/_static/ajax-loader.gif create mode 100644 f29-branch/_static/basic.css create mode 100644 f29-branch/_static/comment-bright.png create mode 100644 f29-branch/_static/comment-close.png create mode 100644 f29-branch/_static/comment.png create mode 100644 f29-branch/_static/css/badge_only.css create mode 100644 f29-branch/_static/css/theme.css create mode 100644 f29-branch/_static/doctools.js create mode 100644 f29-branch/_static/documentation_options.js create mode 100644 f29-branch/_static/down-pressed.png create mode 100644 f29-branch/_static/down.png create mode 100644 f29-branch/_static/file.png create mode 100644 f29-branch/_static/fonts/Inconsolata-Bold.ttf create mode 100644 f29-branch/_static/fonts/Inconsolata-Regular.ttf create mode 100644 f29-branch/_static/fonts/Lato-Bold.ttf create mode 100644 f29-branch/_static/fonts/Lato-BoldItalic.ttf create mode 100644 f29-branch/_static/fonts/Lato-Italic.ttf create mode 100644 f29-branch/_static/fonts/Lato-Regular.ttf create mode 100644 f29-branch/_static/fonts/Lato/lato-bold.eot create mode 100644 f29-branch/_static/fonts/Lato/lato-bold.ttf create mode 100644 f29-branch/_static/fonts/Lato/lato-bold.woff create mode 100644 f29-branch/_static/fonts/Lato/lato-bold.woff2 create mode 100644 f29-branch/_static/fonts/Lato/lato-bolditalic.eot create mode 100644 f29-branch/_static/fonts/Lato/lato-bolditalic.ttf create mode 100644 f29-branch/_static/fonts/Lato/lato-bolditalic.woff create mode 100644 f29-branch/_static/fonts/Lato/lato-bolditalic.woff2 create mode 100644 f29-branch/_static/fonts/Lato/lato-italic.eot create mode 100644 f29-branch/_static/fonts/Lato/lato-italic.ttf create mode 100644 f29-branch/_static/fonts/Lato/lato-italic.woff create mode 100644 f29-branch/_static/fonts/Lato/lato-italic.woff2 create mode 100644 f29-branch/_static/fonts/Lato/lato-regular.eot create mode 100644 f29-branch/_static/fonts/Lato/lato-regular.ttf create mode 100644 f29-branch/_static/fonts/Lato/lato-regular.woff create mode 100644 f29-branch/_static/fonts/Lato/lato-regular.woff2 create mode 100644 f29-branch/_static/fonts/RobotoSlab-Bold.ttf create mode 100644 f29-branch/_static/fonts/RobotoSlab-Regular.ttf create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff create mode 100644 f29-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 create mode 100644 f29-branch/_static/fonts/fontawesome-webfont.eot create mode 100644 f29-branch/_static/fonts/fontawesome-webfont.svg create mode 100644 f29-branch/_static/fonts/fontawesome-webfont.ttf create mode 100644 f29-branch/_static/fonts/fontawesome-webfont.woff create mode 100644 f29-branch/_static/fonts/fontawesome-webfont.woff2 create mode 100644 f29-branch/_static/jquery-3.2.1.js create mode 100644 f29-branch/_static/jquery.js create mode 100644 f29-branch/_static/js/modernizr.min.js create mode 100644 f29-branch/_static/js/theme.js create mode 100644 f29-branch/_static/minus.png create mode 100644 f29-branch/_static/plus.png create mode 100644 f29-branch/_static/pygments.css create mode 100644 f29-branch/_static/searchtools.js create mode 100644 f29-branch/_static/underscore-1.3.1.js create mode 100644 f29-branch/_static/underscore.js create mode 100644 f29-branch/_static/up-pressed.png create mode 100644 f29-branch/_static/up.png create mode 100644 f29-branch/_static/websupport.js create mode 100644 f29-branch/composer-cli.html create mode 100644 f29-branch/composer.cli.html create mode 100644 f29-branch/composer.html create mode 100644 f29-branch/genindex.html create mode 100644 f29-branch/index.html create mode 100644 f29-branch/intro.html create mode 100644 f29-branch/livemedia-creator.html create mode 100644 f29-branch/lorax-composer.html create mode 100644 f29-branch/lorax.html create mode 100644 f29-branch/modules.html create mode 100644 f29-branch/objects.inv create mode 100644 f29-branch/product-images.html create mode 100644 f29-branch/py-modindex.html create mode 100644 f29-branch/pylorax.api.html create mode 100644 f29-branch/pylorax.html create mode 100644 f29-branch/search.html create mode 100644 f29-branch/searchindex.js diff --git a/f29-branch/.buildinfo b/f29-branch/.buildinfo new file mode 100644 index 00000000..dc28eac6 --- /dev/null +++ b/f29-branch/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. +config: 1bf42a3192ec6a62d96115c18e727069 +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/f29-branch/.doctrees/composer-cli.doctree b/f29-branch/.doctrees/composer-cli.doctree new file mode 100644 index 0000000000000000000000000000000000000000..aff6770404e598f000ade95aeef459638ab26d1d GIT binary patch literal 42707 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 literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/composer.cli.doctree b/f29-branch/.doctrees/composer.cli.doctree new file mode 100644 index 0000000000000000000000000000000000000000..20f86cfe8759b19552c94a65cb41c77948d6b56b GIT binary patch literal 253746 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 Wv*rff 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�Kf{2y4XTr+^DFp6*g)? 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
2WxO zO^z}|N9jhpQZ1<=$cwNX*2tZLDsHhGyb)zkHr!m(7X9bPd z;QKna(Tz@SyVYj9R;jryw^4&>@T`9t>Y`?27Q_UN__az4ARd1K)^N1d>4eRSycDg2 zGoolqtux=M2*(4((hEMUxpu>;10bmxxPWNL zp43aKVdbbF_{>GeD>XlGX6h&i=W--o5Z>-+GYAvF5@1K%;5D4AGV9ktIJo^|Ys+m_ z5VnG)RHgE6#w#;$;!{E2j!JlP5**mK@7S?paOVMlw~eW0dv0INJ-QDlgMHm-2ll`b zu}39z=RwOMXmu2>PoBH~O`w*o?b&K-8oVN>IU}AXgtRG`^4)NjPUD61b(mr-bY@@) z)IzU&a5UNl4mDp9YfG?S2_Vk6fV`bbx$ztDgCTgh4}Oa}s(~YKf)`$kudwj81&fW) zS*UpaoL7hc!A&>Ro9N-2gLwzm({FTO`3BJQWcre8kG^>7N7EB$l|LqtNg3e5mZkszlYRc=N-RZacVXAIeUx$#zor`R~ybeOazx~op? zJ}g=CS=?IZyqb59_inNV&<65TxV_1H+qm^VkOXME~4344>$qEu-*>{&{o^ zKG8o*o8S}ugFkvl=pTHAI-!5?jYfq2!RLtx{j-QX9K}C)fXe6^DvS; z1b;fw7|MW0b0`s$V%nRV_U@Uc{7-w2FHx?SD91~b+a=2B66JDpAQ7)D!2TKH5nC^JHa8jzZO`x^&y?1+rsq9|zPpCPlzBr;RcCDcl^iB!I z9vq)eMnir8i3oTD}Ai)FMx!ZKy@=N83<~Y)9Kr zi#&$5p%%FhZ9^@Bzg);Hg73j+7Qxq2F^k|sVay^3pOFqK{uJOQMxoNOAc2i6$}Lpn zY#5nI#4L`d?9Aebc{7V+-AOG@vp@1F6CX%m#fMDi$b-;_@zII4sKJUZmMw5bK*KVI zMRo-@l$egKO7#k(gOCj&YksC#7x9mho|3vKsK*i`j>WUmPTLdXLvGLxF&WvB9*eiY rp)+iEf^2KcX~Ql7K_P&hlnp3$wZ!F3;xdgu8*8}H@;!-FNmKtHeuDoU literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/environment.pickle b/f29-branch/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..e1d9a217c4fb3990e5c3162d0f8cbe2bcdc88e39 GIT binary patch literal 2277347 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�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

>Qa=l}S~KMoCo4 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ļ(dOPp)F{7NUJ#6>Pue?>G49W{u4Uf!Rb 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Ƚ$rm7^RNI5u^3CR49l?+tFQ)Zu^t<+37fGM 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%0ATbsUrM{S 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%0AR0icALRYpf9K=O~dubdDQK^6qgG?~8_O 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ⅈuFxz&T_HH7nf2J*wDx3dnk{=F3j=& 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 literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/index.doctree b/f29-branch/.doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..ccf4e0a1fc813d86797249b178e6b3880136a147 GIT binary patch literal 6432 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 literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/intro.doctree b/f29-branch/.doctrees/intro.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4bb3564e1bcec4291c26f5500d4fe3e3d74505f1 GIT binary patch literal 9111 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 literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/livemedia-creator.doctree b/f29-branch/.doctrees/livemedia-creator.doctree new file mode 100644 index 0000000000000000000000000000000000000000..15612b08d3f08c07e5dc7b69a6d65eb7b8abd065 GIT binary patch literal 168643 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 X-X-3>TYNo>FI?P7pQNw)Q~CcN(gWlH literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/lorax.doctree b/f29-branch/.doctrees/lorax.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a66cab873fb870b3a9dc843d0141c5069655934c GIT binary patch literal 70335 zcmeHw3z!^Nb*A3Zv>uj)Wf@`NLSQ^L>K;EZU|~cCS+<4bk&wm@LX?@B?waW?^~+t= zlE&Zw;blV+UQLqS09hdU*nD4jYbj^T9MpIA z=iI2|hGDNU*AKxYF}1!?3&23Mx!QDt0Ezhb#C`E}wAwTR5g9GINZ=E;6o@ALxEFuTpOX_4E&?hDZr^=Cl-`aZPZHTeHo z`2X4X|60gazpj2Oh;FWr*RQYNaBPju>RhL`XfYIB^RiyUZ99i6&T+TxIk(SMn?Ka^ zYIQfPR6DIhCDlV?=mmG7=XUFM?q`n9&6&sRyQ9m7=muJx)dr2;#d&@j_J{0nyF&$n0oF4W(FK}MvwrftKvY0OBj`A8P&)55oA~9noO6Rl z)#-Un&kax$TK0fL4O^jqHrn$Yr{#ri%?({=zR~n5&e1S%YF^iC*MNtH7nEQVoq4y> zYc4v?#zH+TpZDm;ne(bH1aTUn)Aqa?s_P)lap#(-r{nbcZLsIKPODQr>s0GKFj(^1 z=Ni3Eo2)(6L~SwW1)-uB%{kxe2>l3PG&Spxhp8Lw1t)ZS3ts5eN{R>4rqFA3n`q9! zX}OC|-92aWLcOYud9*{bvw*)~3mIA!$6Kg4_foT<12E*&8#T{4=k)>%E-XzS!;WZ0 z)w-mjk`nFM?0}i`=yWEM>7}06?F5am(?jc3v|-vX4IV8#i)X0Ud!SnPYj{j7QKu9x zHgemU^4S=@ZN4f+4hsEBKFrrn?#q`=JUE-O=gy1)@Wo_LktbG zHw|1h(kSj+HRNbE>mMZx_OS@fEp2ygaBQt)Xm@lqIxrJ#rkQf+65Vs_vT&+8X^R56 zVSxMTH;eR>$z1=%=(?OfQbr=yO&`}Jp}3A=JQExy7ZX&RFAEe!G`VeXn#(*He)bu?54qhmy~5t6RFEoLbOK=%GFkl zrXvnUUY@M!c|+!Vtv&T`qo!|-GI3-gXm0d%axbOVc!lk8MOPozu9BmSsP=h;c{MI( z0b&dgBTLlG`|Dw>>U;gQ_{kFiEjxu-5Dh}#&8OAkBF_{LqT8E|(CfL)nYku>CTlEx z;4SM>djMDXAY2$s7oAs?>t~#D*ExCW#2xn@o_5OTocoTPI(_uSlvD0Gr;Z#yGI{z4 zr~>@^|bq=4Hy7TB=cOE@{gr3XYUgyH1bN7kUTtLG)IeGZl_)veaOTBGM2o;-Z_kvoo_;v&v>dS@x|{u8H;sWfJ&`~pSUrRQD&#zOc9{ga}kUx!>BoT zoSHm*@AS;%sk=DmeM3y2xOe*Gz0>G$>B~I@$#VHANG2>QK|Tg9#&HZ-MS%PiB$ot9 zJzCRj%HNYSR7YbMTFrw&*QN0CmTu1ryxuvFW=j5U9_(#Dghu8O-q95&X{wKSf!lN@ zhh3xemvLrq$YEBxM*elg8Mzn2RoL3;QmvWs;GNd{8F&>f%bQR>-kNBeq*~}$DRB{x=8Ndx#SQP@QGoPig7l?K3Ldv&6`|T|aC=xB3Ms9? zTu4*$W@gpP{^K>+6&&EjaS2 ztn84wUK#MaR3{wcwb71hzefubGjh>@Uq#zgDlZdEMOy+d4ADziQn_5Ou^^V#4iU>6 zM4Rq&n|-WR=m7VQsc3A$Ys2A0V+`4lDdJ{ zuXSc%i$S&1yMUmnH)H2yEvbex=NcSMrLtzE;|M_{mzxzR>eolxAWQ%VxV$SgKgeMKVg8*AKLSN9({y-%N?}-(&ReaIp*49v;;9;q7+2znFe|wE=TP z6`~B0LYPu?f-yTq(484jueIhnO|1ed zqAftYCfk9PSpWqq-V}-u1!`c&lDFz)?u1f}Y>k9veXai>4Q+EdArk)#sNl|tfqrC6 z%YTU=J;>!|53c0my-1LfKV`3c`UjApmmSn<1C75FCzF9G>3)sy2QQm~BGi(uU?N?+ z80@m{z=C2;h%Cq(~@Gj?r0W6F2i zUw~BlZr3oW|DzTg33u(eLA`U{LHG#Ko7Q!KUYCO-G3WJo4U@)r#d=Y4EuMdf+H$Xd zdp_Gq*X}mTn{@4{tZeNwuHDP2PIB%1SEC7hdh}m|e@*!h)AQ@;&+qZ`@8j>8f&V%D zJUsCKQ2cye{Cq+Dd`bL#nSaRk_+Jqze=2_d3_mF1&&AJQil4s{KYt^Bz9xSD7C*<< z`j6Ak8vpC!=^NtRx5Ur4@iXOrhyH^5V7Z;dmz!R*vIc zJ@3IjCJMD=z&q`g)+$ExkLR<`Xnrl|Mxc4zUk;qNm%9fXj=R?S7!P@Ib$2wB8t3<4 z_;hY60lTOwwf8h z{u_{dj-_fPV0?XpYs>C8G7mDK z@V5m>rM~`mA;ZW)X_wj^f}JAm5L-&%-bjR{z0z#^o3MZb-Q7UzI5`{Y5^;pJlsBon zR91Ey7~S1PbsF8J$5pAjPa`>s>aOU_ORu{<(p|Z`N@>FOax7IV0qgE0OOf4gmhK)Z zKq__j#Y{Td)?&ghHi6Mxtk)9WxK!TMcbakkhfzGV_knzdl9u;g%A3?)Dl5AcjP}k` zokn}+XA5hU{Lmbobo_NTu$+gGp0# zcialz-YB@lZa}%WZqXU1ZGPBrNL!-er?vXcu+gQxhYd_nuUBAPdPXg?|1od|wg1I@ zS(0l13zRpZ_TyZbCD+zFym=R#A9P-YO>ndkZg&(*Gu(VuaPw=$xbZ(p)( z{--!+wpJO?QC}}IpdI*GvfHzj@}?k&3R@n6 z_6u&DV%+#w6S+W;;Kkp^IkUCHAc*o>2%^VTi69{{5JZiZEx3gspm=V1AYdB}N zJ{ZhUUJEnyxGFItBnD=v(Xs`%Fe8*`H0jDQv#mTwn8D5qT4LApOgmBcJ0s@y{7zSh zxvc=HM9d4AG-uR$7P#c$3M=XOwhP;x^;d~9RILOkK&hqj??v6f*6Dn1lh`^*c~h`O zg<05ok)BEJU&N==*ycnVQSkXPR-9=W?HoduH770}?LN>zTz&yY&IKW-S4>XdC31mU zA*DaZIkPp=pqBDlsHMkMiCQ5sP)m)LEx3hRp~$02SB~1Ta#`-{R~m1n=pJXhetO>QCczQ(vQi-Q2CQZSUrNCIZ z!Z&R2Z}62F+{=TsD_FrQ^_^ziZ=rY~t5R(r z;#{w4?YjKiAAKMLDo)W8qj~1Jh7*qV4Oi1;;WT@Pe&QjUTL=dH=%Gq=MDMn zB%$*<%A0@=mzCWHMtR>wbsF!I9#^IEzMI>wpm!-c^HS?A=0E(^yV61xTg7ev(N?>+2ZU!vQT0zRr_wua%;i^#24!K|8;kUwKkHzestL+DT<) zOKi0Buc=O>o%FaWwexRCj-osIMAuzv?L>rDo_(S_-=yfyXAQk#3vr*_UzUbmUVv0; z=nf_wt)bg>$Z5LQ*T!@xRWs|CQ6x0=dHGDlHI*W^_B&??lVhUy#l0CTj!YcqH62wQ6v=awfRgW zwe>ZWH>s^uR<`6uTi;G~8f~S=RjI8%L2?w;R?&su7j2d2NX4{OrNy=N(=0)DpIO@a zs|84U&v=7sjYuRd6U{oWo1ilwDm8jPNS{#xGJ^vFG-G~+A6y6 zQfn)`0C~=t(p4)ZuBki6i2LmRvNUyj0aB@{B_>VLR6F8%*-4kq&F#>cy!OW8M7rkK zzaHg6U9ZdMB(AQs9`+o{n^4zrF3g(lU7?+mid+Q)d#V}JUmE^iEcm;v7=Qk)L@weJ zf;;~OoHJWL416fB1s{4`mGBV~BR)ZmmMu8x;Te2%jE)q_HJWtg@rjM)GD7UCg? zY4%Ba+*yUN(mG^{S(-KIDy6$_|gl^BPa}~?-!i@OfgRVpCWRBFu|w))0{I~dkn%T zuZ1vrT$KnD5(8n>XxV~W2oowensns|D`CHeJYZA7%udpM&RF{*cUvK>eZByx#M&P) zX$saX#k~;+N;=G_0a!(ChM*Ja-8clrf$#W=Yv~!a$o@CL7y$Wrz9>mRevR@b0Lf)# zx1Uk_f22B%Uq+9sQtkhV+b++ykz|cZxSz5RuR11LvR{+$Y;nF5738D}5bK)_u?T`!nvoLiqbH z1xO|S{+LN~@OSNGt)@=jRR=Nh_Zo7$l(;@hiBXVROXvRscmUe|XFk_Sw0(#2rl5@q zv(UDL{Y+z9nVZe{$#H9l8-G2K3!DjF{0*ElTZatJD6fSxdR&z_6A}Yw)M(j)TR0PH zH=1yyD8 z<+U(JkE;@MLSkT!8ZBFJ3v)vCMw6}_b59ePiyh9d^fdLI)=5U)hqxmPq3&l3kV@3O zk4bY-cT3hNXKzX>>pSlF%0wmEvhr%l{ZD~Epz&ApB}$_4G0K~QMk;K1X#AYu=J$(n z(Z(&MT`qmUSAq(;jY+(M&J$6oRk~qAI@}}UB3R@ly zCj>X;V%+%G6S=^l;Kjdzb7t$9!6D_fa7d4<5{E)!;E)mAnfhuaWY{4y531u5idQniNu0~Uu2~_DM-RF#|-{Ed6gsT5ofK;ODH<&a9 zRhEL@d55|R$HBM0q1&J4PSEUD*_ch;)z-X z7$H}0FYM(#y#T31$dyc*f)G2xe-+*55I7xq4kGPW61*$Evk9~e{;jA9YJ5vRZ%H-2 zk@6~QCt1`f34EiKeeGX%3ny zr|Fhl8kjKu;nQS-MI40P!pQ;7U5%INeHsCcSvTu#NlVS9<@Ns&Tmg6gkS|9PcYjZL zQ*cLxS-30dU4l2O=C_j!FI#soFJt)0aczhfeRs_vt_DX5~tEL06|-N@b1(GonJEyk0- zK;!~lf+N4qIkPp#po{Wa=%U9}i7p{A&_#`wEx3g)p>Cr|SB@@xQ>X7nSIQYn)0)W0 z`Z?~nLdg1H0aA&q4=`yCvR-n8=Y-f#OFM4mZSHf6e01#uor;64h&|^9GXvv51;#(@ zx@zg+ZH1-i*6=?Ao`K6xvbhq(;jY+(M*K)6t|WN91J)1U}fu^}O>zxzldylhqRGS{E6a zn=Z?Bb=16VeF0L5%r#7!gUlQ64LraSmkGnQRJ_|BCv60wy^nI&l?LO|GisUrYrq-s zw=Z9oB>whN-W2>%VHW>wuTuLQeF#%^tdWfC?p07 zsnN0pw@@flax`fSg`-L3{SkC6gMEKQv}fp|R$QOk_1y5L!HO@Hh<4U+K{76ycY6ys ziG%JpmmXL0h1Pe*c#qX%kAiQuB=!}CW!ifS=9QPXmb+>i}l>*;5`E^!j3p+${v>tyQW?qIyUblH5si@8$n|# z-W{zyXbPbR{mv*({Tg)rv+%#A0tl#a*FO{Vsvj`GUy0ANHUHnBo5R!w4c5I<;DsJt zJPEUVV~LZTa@V=jt3flJ@;T?`Tby!_{{Bd*960qb>>iw$s5L9|Oo0P_eVo2l>GT#R zy8XEckvaiw?q5I`^2L_H#Lc%%9D&hZMCZ2`CN8|_1v4*r{zNC3SVo!sZjAyuRHQ5i zg_!2I#kom!&kvZ?8ojK6PL2lp*Fr)3=i(1px83wH{|(0+ONU6UVmN;Im7P95y=^=A zCdJ`9Ejs7h;w~xYd;^C^%+8jB*;&2{ULLg>h!^$7LLDC>PThBk5}M7D8p_!p=(Mq- z3-t4-Zr_rjFPCh1ftbXQEpYPKuuzmw3xO-#QvN3VXuxa|vM5bjR}M_6+`KQ$X1Mo(GQ*R~!Zh zoeCBvt8`E90jEOg;-C1^Pudn_bi>j@hqeZ^F}hGWYG66QPu&Y1C75pj4{&GLgz|G) zVvYA~(->sbZj)f#s6nJsAnM5!6AaAs7#sgPia5_3qLk`?v&*=v= zlN2rsk2}PfbMB_fEtTg}Ou7k2p~uuT);Mhs_bkboX$fY%+-cUz)jBQHVz9ys%3g8q zp+ef7^Y~(zCzd>m6;+9a+*-LEbX|;i=j#njQ85r=18hn9v1CW6B2?Av;4qk)cdh}? zs@=i&$6}gGJSS>r2Kxx-QGW1Ml5578HbcmhiKfBm){C%(a zVz%@rm(kMKh_NVBovo(HCC!ipW2y}ar86ayXewci`P?$(*p-4bZP=o;x0+jHpGVEq zZU((Fcy=ryx)Kq4vbuDw1gvhkGhb$_YwWwCpvjzVmq!K#$eNC@_1o@-)oX+f9fqP~ zqwz#7zW;Ynz5zTcLyf(h4s6reWA=N(WS+Cdjn$CQ$)1r)+?lvI~ zMw|3G(pIZk4I-jgGJ5fQ+>7=5^|a@O%j^RM#P#SBQy(L6%jKgZA<>35w)74n&RYM) zsIoK#;3(LAMwX9jS#DagE(s}~@$g{0zVD3W$Uu)7)HsVa^}P9huQBkiA^{PK`&j)m z$LM53*{Hi8*b4Q2N;!iDP{$K^ZA6}GnPJ!}ttmEsyck-h3~S7wegzsg-EnHY222#p z1RP5Q>Z)Eq=G8I@u2by?A(;{n_ZCqcR`{IGv zIZbJW%(bT9xKzV#>Wr42H$&1fJz6LsH}dFV>SFoczYO`VEj0d^ilTxUG9=kNJIf=P zl4CudOyMlWCzc__%}XB{O|8*#a%aeQU?~HxYJ~BkW3=I!Tk1EL(Nf!Eqr53F8hVi- zA2d<=1&aBN{A>zh&i?Z-JTcy~??5uLoWo$cy3mrHVjzPSm zhE?8X$E~sEN}gzPVXESeqNUjl)O1D{W_hn(hP4}ZkBq8Z0F1?^OLZ5q1-e_B?5h+IOPpT&T%*@%Q!Jd9EE=sw)5X?* zihQ>b_;C43YF@_G@tuBHqJTD*5<9q+kcSPB)iI!8@76-aIoxT_Hx^<+ab9%gl}E(R z`I}b6ZfL}7(z=69xoTNe2`ETJ1RdP=TXPVoGhfp2 z_Q31W5-LYmuxlf5al~Z}3=rEWP%pxw7A*J9(|W0jKq>Rdf&GdzX^Jfz4l{=`mlY&FlwECxvSddq8&W_C*^v188mK0xf|vU42Y!-6&B`@-N})`TKj8|c zEzDD$gm^PYH=cy3-|Gu36&wC&y-5uKF#L${%=Md1FPtHN(u#cn&zsL+HEB&WMsH@Y zvAAWuj!qt&@3*T5XW6{hoZE8)Toplii1)3~Hp~#=VPWuTg;9iv&DLu_qEU)i@MkdV z(Mw~uExTSeW-;UEzem;q&w7(!Z^$!xZ;C-1_uF7d1mQL#2uJOZ8H0OQN&y)$xD8xT zEClzn$Q=*CJ>vfuDxdOS%YR=-jEom;`hoxBp!eTEf8K~c!;!W#P>r8pe$gI#xNB0n zNgIW15?xL)m85##n$u1cV0#2KAbk`4X!m6bbF)X0q7_6bX0?t$Wf8q(La1dGp2PwM zZE|HuBd-gvy{eW}%-^8;lZyF5shCTxH$^RfSJr@T*vQ2VY31+Z{qPR`C28evrxZ|J zE5C%?xmtN$zE%p+a+LB%(c{0x?4mWEp4~}CEk_XPvWh7t)&1F=rYf$ORjDA-2`-|V zl2q7CmCt4EB;QeN7MAI>DKKF~|2Mc#(bX5PfRz+|{hq7^J+xVJGo-O=pSD7c{ccV- zSZf(6c62MM&(+xL^EFlpm!q>Y(3^i^hS4J9WJnA3ol)W9d2~(1G@3a3UpY-#T%)I? z8nw>W8oeU=%!JTptSr*(2-{AvXH^{>nNZ#edM!nHm7!f~ttpCotE_9!uImJ|x>OGLtOvP35l}aV? znNA^%1f4LiEy^*%wzB$I{%H+7r)cM`%VHo!H_yuQ(Hk3xw;|PRr8L=+e1Jwu0mW7G zJaXr%=5zBcDod85nJzSBp1DO^JcrC_ZeJNSEk>_vD5kT-(OgdZ71!Axkt&1zkWFmO zETXoO6q;M34~KXv72ErR4Lm}Zht>99g6$NwRUW}|ct}y+56W85Vc2BAVh!oR zD=&kxKpa49PbSsHMqqpwo1v(G1Qt^iRn7lJDaEitoE@4?QPVHWI?yTD6U(+pw>$?l z|0JcImZYU$N-3bYmi{;7&ehTa^M5H@j*?cP82^d+MSEN}+&#KslCN~WVhTw0{6S8; z6j#7kCWHya1shDn3%^PxBs<>|6 zBXu)aY+;G&Y!PcENuizM^E@(-GHrM$za4z0SV%RLFQ?KJ%{(k?K~HQ}jOd1EBY7mH zy_RGoCsPV2u9_#1J6AOe4CP9=9NqMwA%~b@w8*ZMUeb+|`c~&IrjJzH!JOtPu8%4N zC6+>~VY8S<(pkVD78VoBue^{-x#49}wA6|~l}bZe8o3$+vY3lrC)YT%Oz_eb)|vu@ zhtLfKH+1`$Zh|2z{hE}nS`rj4q!dsb3U5a4Tqry*e^zG1%K^hY)H7t3(JK4NP>)s* z(_Dq9b?L>xLfmw78gLX?vTKPpiB+;ewDtztVeh|zLY`uSGA&=26*W^vl(uR4TA-*sSvCU9?*I2@lu9o=`-$Gg& zOR$fS4}1|{^vGyAIN{>$x~1nwA5hZQoCS7L{0_HFY%wviHU-9o6c%xJl+)@wmVQ3J z$<+=D!2@uIZ8O&PiSJ7*S~z|pYKLy7^#Jy(s?Jqyo<6Pnt7WwEUen46ebLB?Mp0?5 zjg1)fsdW?d3Rzg>d?PH5TI7_A^YMkx&#H+K>o@kv78z(odx7}Sto&|RorMgyb7*5O z7DTZ}3ZHa^*v>Vn_Ru0yyh!KYbZHv_e;J1l*l5obeN^MMtN3bpj&^S002`c})&zP< zLo1Gl9a}-Cj~%}9ySU+bSM<+ApbW=EH~bQNDaA1(nCeK8ypBVLYU(gAojFv~EIuYclI+gOMv0W-R7iWwqm%QZROZ@E?9jd=r!{TaU& zGgEvjK;fVvQNvK3VhbntfeJT)%fZ3Y;+qCCPn7P^VefqI8w?bg9X|M-darm#bvQ-KmNb2OX-Wabt<*ipool5IG$I1>4#&=f41NrGSTBiZJ8%|@Cg#}y=;(-j686us$%$!1od*{N&)o+ zGRPYd}A4=()C4u@}N&&?|{YK=zc%WwaazNdOLiU(vfO?MxbzB`xBW085a*6?g z>TTz=)hHlj*W!N^W4iw_nl;5^ALJUCIf^MDG1ncAd!)~W^FF4b$ij%2#~unbq?}~L znoE6=^RlN< z!Pc`->{(ZPu2lPobDhLJZ}=#s5z;3*`22$XCj63@G(n%M&_C3Hq?iKAU~l{zo)Vox z!ryKnT7zF17(R}}Tuz*xP*qkMtp!m&J_w~^ah#NJsOSsKO`@$VV5k&y$Zv6n!~-t7 zlFh1mdWZU~O0>5rlP5!;%kNzkWD)h^GnJD4naWe0rV;a0!{D1PTbq@x8e=#r$nzTL zwlX5IuMzhEALe!+Ml)m8`XG@=Qq5hS86`6{!i;XCQ{LF@-~(%gsCc68e*f>t0^(4; zd`Pju{3ekbgZYM-!F1P&FWBw+$(rydez1**_qvE9(RtkXrjKot41CJ(3vnDbPxEB- zDJaRFiG6QQ=PfJiL#5B*NM?Md&WHNf=zvoGRuNUAI6xgnyc}?vjkEN5J{&bsva1<#j>k`p1n?h<8`=`?A!{)-R* zpX1tJKkA4uYYtJ_Z&S~U!eP_$cgh>8aRm%TuWC~Q4|SUDOz~Mnj0B8 z#VIbw#HoNhZqSi|qOo`=Lnp|y0@Yx{_mYYLexrwhtBvnIacCAt{1I$K%YnzX(>e>y znaAjZyBg@;27OfnNuY)>R%jY;-an1hC#|ZPA?wM`DA4~sMt^*Ce%=zmqKwRS1>vO{ z=e@sxpg8?k-^c^|mMfD{PJ5<6-m5&>Ua$-`cuoxXuWf^?E^~qz(j5N`ci7V4XvF{yUvLegN z-5JBBe;BaQi8f8b9egCEgO@a8pG+yh#^LC%bxt66?u`A0{4kuBE@!^}Cf)Qf z2XB9J4OZIGda^O5+pL(MOKq%tznGs(eq~uZo94*cxWAd_(ZY{3d_>#oo%7{JSQe*3 zTV*1h7Wq~Bh&u-8wC52n^3KEJ5YlPoe=56~e4%^Le=Q+zum5lkI50@DtNaj=8&~{W}yf)?J>mu~^Cd!cvDm9$^Bpts+oSuPmQ{@s5 z`;2sSM}tEb2&M!$bQPB?)G%#ecfScO!0L}9W)i9rI_H-oASJx(oX5w%xXY`7)2vjB zAS8mh09r%_W;8E+ct;0oNz~prDG`wrbcACe~b&v|sEAJU)w zbYjUh^kyn_DRgPFhoa{BY{Xl?4>(4S8r4B>y2{ya{9zD9pKR6vvd{4xFc68`l4 zFGCt!mEeC1Pmk2U`UrC}#av7=2UA@86xaL+*ZK(8IK{P1aZR8^1yfwZ6qi2LukWK` zzlvgUwdrH^Pt?Cs{~}9R|GE^9q-F8w78M~Loii%Ld%70y82yXIqqFLSc(ln_h(}9q zLOhBc3-QRiX7O0{`aT_~|M0;7Q}Od>_&GE1|6Kh1rTFTWWApLg5S=rHuJCdvc>bxR!XY|6S_)5f_`*A9JCg*#FZU99tW05GP}A zI68IbiGjY4xPE=Kf$qH>99u`hr2j)b9lyqQC#vwj#qH&P8$VP2cjzyn4|l@+e;1oN z0TfGpqxoh0A-pB-^;OLud;k77*{OeF#&qtTEbOJyjN2H-iBNLo;y>~H z&-fvpg^8iJR(q547LAF9u>LM(^VpE(cD!f^S@fU2F1~ zu5r8f3tuNY4e_s7n}hgC7*-SpTolJXqhX&qXJqCb983=FN@ig^jPin73nJbJik8jW znEC4AkkS0w@MYrhVdUs4T}3eyFU5g)B6h>D3+?5+(1xxrjGiM0c3x`c3vMrsbusJ} zQt^28)MxN}oa?gEUa^h9nwZ0pt%OwTOUhWA(2>)*Gkh}%4X=2GSi~tZ@fn^k@O+8q z4W5@_)EY;ONQ04eWM_-kvgIcJ9T#C#-PJDRz{8vOm}SalcXn*-c9vu zy+C2MJ=iqY*I1k<*(YI^dz1Q$w6$M^!;Vtd8Hu*sIjL4a#IqhEOQV(JD0>+GN(+xP zcNh_~MVPF(;)XhHP?`y&=vGI|3WtNn41w-z9QWI!Hw8{pWQwFNO}8*NNCm%(;bf_` zQ`+&3%d010n&5`Qko8iVGJ-O*XpoAaClhQfRK98`yx=v3+)5`%hZR_C1zPYRc*84g z94Yt>FVN&+U(ljI4#G3OmdKT(&fAV@5C)8Aeg$*0TWSHj+Oq2lHoW7V38$({1gZ%hG{|7%F`7`x*5(-ft>K%@LU^405dcP%p|xj z!Z6ori5QU%$w-AEB-c?4!;E^T$pa}omFTD`^JPW)u0vL9f<(g^MT?~HsHPyb%BI>s zkSfbP(_~$yemdssN?T4gCF>T+9l4QKHvM@-n6xx2QXs9DqYe$?JRBkzi~gtWw3xPR zq?;~bR`H4;Cd>zw*YO@EN=9KiHFo%1I9J&p=kwd!+so?C39T-*S&}eR8e2?qx2(+wR~9faaWq5!vo!z4 z;S}9ek{(#S`@~kMy!YYL+8e1bVN>L2+LR-PEU(g7sv0y*fXJU9N6YcdfW{*vDy* zAR8`z^jR1;lL1gfV@bs%THO&x4Vde-`wX_xC=TBcNEfzG+R))-i`pz>kfCkaABG7K z*yEs&60vy~@5EahCW+wgD&+4&6z>*RoZ|njIIv;5S-o0%noCTkWF8tDN%uU6Os4CQl2}v<-cB`9DTa?HB+6 literal 0 HcmV?d00001 diff --git a/f29-branch/.doctrees/product-images.doctree b/f29-branch/.doctrees/product-images.doctree new file mode 100644 index 0000000000000000000000000000000000000000..91f72de6573585c0f835af1d0062b41622afb26e GIT binary patch literal 7055 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∈jth%prN@Cy-R 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 literal 0 HcmV?d00001 diff --git a/f29-branch/README b/f29-branch/README new file mode 100644 index 00000000..615e8738 --- /dev/null +++ b/f29-branch/README @@ -0,0 +1,5 @@ +To build the docs for this branch run: +make test-in-docker +make docs-in-docker + +If you already have a welder/lorax-composer:latest docker image you can skip running 'test-in-docker'. diff --git a/f29-branch/_modules/composer/cli.html b/f29-branch/_modules/composer/cli.html new file mode 100644 index 00000000..19343efd --- /dev/null +++ b/f29-branch/_modules/composer/cli.html @@ -0,0 +1,271 @@ + + + + + + + + + + + composer.cli — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli

+#
+# composer-cli
+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+from composer.cli.blueprints import blueprints_cmd
+from composer.cli.modules import modules_cmd
+from composer.cli.projects import projects_cmd
+from composer.cli.compose import compose_cmd
+from composer.cli.sources import sources_cmd
+from composer.cli.status import status_cmd
+
+command_map = {
+    "blueprints": blueprints_cmd,
+    "modules": modules_cmd,
+    "projects": projects_cmd,
+    "compose": compose_cmd,
+    "sources": sources_cmd,
+    "status": status_cmd
+    }
+
+
+
[docs]def main(opts): + """ Main program execution + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + """ + + # Making sure opts.args is not empty (thus, has a command and subcommand) + # is already handled in src/bin/composer-cli. + if opts.args[0] not in command_map: + log.error("Unknown command %s", opts.args[0]) + return 1 + else: + try: + return command_map[opts.args[0]](opts) + except Exception as e: + log.error(str(e)) + return 1
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/blueprints.html b/f29-branch/_modules/composer/cli/blueprints.html new file mode 100644 index 00000000..bace2304 --- /dev/null +++ b/f29-branch/_modules/composer/cli/blueprints.html @@ -0,0 +1,728 @@ + + + + + + + + + + + composer.cli.blueprints — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.blueprints

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import os
+
+from composer import http_client as client
+from composer.cli.help import blueprints_help
+from composer.cli.utilities import argify, frozen_toml_filename, toml_filename, handle_api_result
+from composer.cli.utilities import packageNEVRA
+
+
[docs]def blueprints_cmd(opts): + """Process blueprints commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + + This dispatches the blueprints commands to a function + """ + cmd_map = { + "list": blueprints_list, + "show": blueprints_show, + "changes": blueprints_changes, + "diff": blueprints_diff, + "save": blueprints_save, + "delete": blueprints_delete, + "depsolve": blueprints_depsolve, + "push": blueprints_push, + "freeze": blueprints_freeze, + "tag": blueprints_tag, + "undo": blueprints_undo, + "workspace": blueprints_workspace + } + if opts.args[1] == "help" or opts.args[1] == "--help": + print(blueprints_help) + return 0 + elif opts.args[1] not in cmd_map: + log.error("Unknown blueprints command: %s", opts.args[1]) + return 1 + + return cmd_map[opts.args[1]](opts.socket, opts.api_version, opts.args[2:], opts.json)
+ +
[docs]def blueprints_list(socket_path, api_version, args, show_json=False): + """Output the list of available blueprints + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints list + """ + api_route = client.api_url(api_version, "/blueprints/list") + result = client.get_url_json_unlimited(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + # "list" should output a plain list of identifiers, one per line. + print("\n".join(result["blueprints"])) + + return rc
+ +
[docs]def blueprints_show(socket_path, api_version, args, show_json=False): + """Show the blueprints, in TOML format + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints show <blueprint,...> Display the blueprint in TOML format. + + Multiple blueprints will be separated by \n\n + """ + for blueprint in argify(args): + api_route = client.api_url(api_version, "/blueprints/info/%s?format=toml" % blueprint) + print(client.get_url_raw(socket_path, api_route) + "\n\n") + + return 0
+ +
[docs]def blueprints_changes(socket_path, api_version, args, show_json=False): + """Display the changes for each of the blueprints + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints changes <blueprint,...> Display the changes for each blueprint. + """ + def changes_total_fn(data): + """Return the maximum number of possible changes""" + + # Each blueprint can have a different total, return the largest one + return max([c["total"] for c in data["blueprints"]]) + + api_route = client.api_url(api_version, "/blueprints/changes/%s" % (",".join(argify(args)))) + result = client.get_url_json_unlimited(socket_path, api_route, total_fn=changes_total_fn) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + for blueprint in result["blueprints"]: + print(blueprint["name"]) + for change in blueprint["changes"]: + prettyCommitDetails(change) + + return rc
+ +
[docs]def prettyCommitDetails(change, indent=4): + """Print the blueprint's change in a nice way + + :param change: The individual blueprint change dict + :type change: dict + :param indent: Number of spaces to indent + :type indent: int + """ + def revision(): + if change["revision"]: + return " revision %d" % change["revision"] + else: + return "" + + print(" " * indent + change["timestamp"] + " " + change["commit"] + revision()) + print(" " * indent + change["message"] + "\n")
+ +
[docs]def blueprints_diff(socket_path, api_version, args, show_json=False): + """Display the differences between 2 versions of a blueprint + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints diff <blueprint-name> Display the differences between 2 versions of a blueprint. + <from-commit> Commit hash or NEWEST + <to-commit> Commit hash, NEWEST, or WORKSPACE + """ + if len(args) == 0: + log.error("blueprints diff is missing the blueprint name, from commit, and to commit") + return 1 + elif len(args) == 1: + log.error("blueprints diff is missing the from commit, and the to commit") + return 1 + elif len(args) == 2: + log.error("blueprints diff is missing the to commit") + return 1 + + api_route = client.api_url(api_version, "/blueprints/diff/%s/%s/%s" % (args[0], args[1], args[2])) + result = client.get_url_json(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + for diff in result["diff"]: + print(prettyDiffEntry(diff)) + + return rc
+ +
[docs]def prettyDiffEntry(diff): + """Generate nice diff entry string. + + :param diff: Difference entry dict + :type diff: dict + :returns: Nice string + """ + def change(diff): + if diff["old"] and diff["new"]: + return "Changed" + elif diff["new"] and not diff["old"]: + return "Added" + elif diff["old"] and not diff["new"]: + return "Removed" + else: + return "Unknown" + + def name(diff): + if diff["old"]: + return list(diff["old"].keys())[0] + elif diff["new"]: + return list(diff["new"].keys())[0] + else: + return "Unknown" + + def details(diff): + if change(diff) == "Changed": + if name(diff) == "Description": + return '"%s" -> "%s"' % (diff["old"][name(diff)], diff["new"][name(diff)]) + elif name(diff) == "Version": + return "%s -> %s" % (diff["old"][name(diff)], diff["new"][name(diff)]) + elif name(diff) in ["Module", "Package"]: + return "%s %s -> %s" % (diff["old"][name(diff)]["name"], diff["old"][name(diff)]["version"], + diff["new"][name(diff)]["version"]) + else: + return "Unknown" + elif change(diff) == "Added": + if name(diff) in ["Module", "Package"]: + return "%s %s" % (diff["new"][name(diff)]["name"], diff["new"][name(diff)]["version"]) + elif name(diff) in ["Group"]: + return diff["new"][name(diff)]["name"] + else: + return " ".join([diff["new"][k] for k in diff["new"]]) + elif change(diff) == "Removed": + if name(diff) in ["Module", "Package"]: + return "%s %s" % (diff["old"][name(diff)]["name"], diff["old"][name(diff)]["version"]) + elif name(diff) in ["Group"]: + return diff["old"][name(diff)]["name"] + else: + return " ".join([diff["old"][k] for k in diff["old"]]) + + return change(diff) + " " + name(diff) + " " + details(diff)
+ +
[docs]def blueprints_save(socket_path, api_version, args, show_json=False): + """Save the blueprint to a TOML file + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints save <blueprint,...> Save the blueprint to a file, <blueprint-name>.toml + """ + for blueprint in argify(args): + api_route = client.api_url(api_version, "/blueprints/info/%s?format=toml" % blueprint) + blueprint_toml = client.get_url_raw(socket_path, api_route) + open(toml_filename(blueprint), "w").write(blueprint_toml) + + return 0
+ +
[docs]def blueprints_delete(socket_path, api_version, args, show_json=False): + """Delete a blueprint from the server + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + delete <blueprint> Delete a blueprint from the server + """ + api_route = client.api_url(api_version, "/blueprints/delete/%s" % args[0]) + result = client.delete_url_json(socket_path, api_route) + + return handle_api_result(result, show_json)[0]
+ +
[docs]def blueprints_depsolve(socket_path, api_version, args, show_json=False): + """Display the packages needed to install the blueprint + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints depsolve <blueprint,...> Display the packages needed to install the blueprint. + """ + api_route = client.api_url(api_version, "/blueprints/depsolve/%s" % (",".join(argify(args)))) + result = client.get_url_json(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + for blueprint in result["blueprints"]: + if blueprint["blueprint"].get("version", ""): + print("blueprint: %s v%s" % (blueprint["blueprint"]["name"], blueprint["blueprint"]["version"])) + else: + print("blueprint: %s" % (blueprint["blueprint"]["name"])) + for dep in blueprint["dependencies"]: + print(" " + packageNEVRA(dep)) + + return rc
+ +
[docs]def blueprints_push(socket_path, api_version, args, show_json=False): + """Push a blueprint TOML file to the server, updating the blueprint + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + push <blueprint> Push a blueprint TOML file to the server. + """ + api_route = client.api_url(api_version, "/blueprints/new") + rval = 0 + for blueprint in argify(args): + if not os.path.exists(blueprint): + log.error("Missing blueprint file: %s", blueprint) + continue + blueprint_toml = open(blueprint, "r").read() + + result = client.post_url_toml(socket_path, api_route, blueprint_toml) + if handle_api_result(result, show_json)[0]: + rval = 1 + + return rval
+ +
[docs]def blueprints_freeze(socket_path, api_version, args, show_json=False): + """Handle the blueprints freeze commands + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints freeze <blueprint,...> Display the frozen blueprint's modules and packages. + blueprints freeze show <blueprint,...> Display the frozen blueprint in TOML format. + blueprints freeze save <blueprint,...> Save the frozen blueprint to a file, <blueprint-name>.frozen.toml. + """ + if args[0] == "show": + return blueprints_freeze_show(socket_path, api_version, args[1:], show_json) + elif args[0] == "save": + return blueprints_freeze_save(socket_path, api_version, args[1:], show_json) + + if len(args) == 0: + log.error("freeze is missing the blueprint name") + return 1 + + api_route = client.api_url(api_version, "/blueprints/freeze/%s" % (",".join(argify(args)))) + result = client.get_url_json(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + for entry in result["blueprints"]: + blueprint = entry["blueprint"] + if blueprint.get("version", ""): + print("blueprint: %s v%s" % (blueprint["name"], blueprint["version"])) + else: + print("blueprint: %s" % (blueprint["name"])) + + for m in blueprint["modules"]: + print(" %s-%s" % (m["name"], m["version"])) + + for p in blueprint["packages"]: + print(" %s-%s" % (p["name"], p["version"])) + + return rc
+ +
[docs]def blueprints_freeze_show(socket_path, api_version, args, show_json=False): + """Show the frozen blueprint in TOML format + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints freeze show <blueprint,...> Display the frozen blueprint in TOML format. + """ + if len(args) == 0: + log.error("freeze show is missing the blueprint name") + return 1 + + for blueprint in argify(args): + api_route = client.api_url(api_version, "/blueprints/freeze/%s?format=toml" % blueprint) + print(client.get_url_raw(socket_path, api_route)) + + return 0
+ +
[docs]def blueprints_freeze_save(socket_path, api_version, args, show_json=False): + """Save the frozen blueprint to a TOML file + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints freeze save <blueprint,...> Save the frozen blueprint to a file, <blueprint-name>.frozen.toml. + """ + if len(args) == 0: + log.error("freeze save is missing the blueprint name") + return 1 + + for blueprint in argify(args): + api_route = client.api_url(api_version, "/blueprints/freeze/%s?format=toml" % blueprint) + blueprint_toml = client.get_url_raw(socket_path, api_route) + open(frozen_toml_filename(blueprint), "w").write(blueprint_toml) + + return 0
+ +
[docs]def blueprints_tag(socket_path, api_version, args, show_json=False): + """Tag the most recent blueprint commit as a release + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints tag <blueprint> Tag the most recent blueprint commit as a release. + """ + api_route = client.api_url(api_version, "/blueprints/tag/%s" % args[0]) + result = client.post_url(socket_path, api_route, "") + + return handle_api_result(result, show_json)[0]
+ +
[docs]def blueprints_undo(socket_path, api_version, args, show_json=False): + """Undo changes to a blueprint + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints undo <blueprint> <commit> Undo changes to a blueprint by reverting to the selected commit. + """ + if len(args) == 0: + log.error("undo is missing the blueprint name and commit hash") + return 1 + elif len(args) == 1: + log.error("undo is missing commit hash") + return 1 + + api_route = client.api_url(api_version, "/blueprints/undo/%s/%s" % (args[0], args[1])) + result = client.post_url(socket_path, api_route, "") + + return handle_api_result(result, show_json)[0]
+ +
[docs]def blueprints_workspace(socket_path, api_version, args, show_json=False): + """Push the blueprint TOML to the temporary workspace storage + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + blueprints workspace <blueprint> Push the blueprint TOML to the temporary workspace storage. + """ + api_route = client.api_url(api_version, "/blueprints/workspace") + rval = 0 + for blueprint in argify(args): + if not os.path.exists(blueprint): + log.error("Missing blueprint file: %s", blueprint) + continue + blueprint_toml = open(blueprint, "r").read() + + result = client.post_url_toml(socket_path, api_route, blueprint_toml) + if handle_api_result(result, show_json)[0]: + rval = 1 + + return rval
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/cmdline.html b/f29-branch/_modules/composer/cli/cmdline.html new file mode 100644 index 00000000..162b3235 --- /dev/null +++ b/f29-branch/_modules/composer/cli/cmdline.html @@ -0,0 +1,267 @@ + + + + + + + + + + + composer.cli.cmdline — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.cmdline

+#
+# Copyright (C) 2018 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, see <http://www.gnu.org/licenses/>.
+#
+import os
+import sys
+import argparse
+
+from composer import vernum
+from composer.cli.help import epilog
+
+VERSION = "{0}-{1}".format(os.path.basename(sys.argv[0]), vernum)
+
+
[docs]def composer_cli_parser(): + """ Return the ArgumentParser for composer-cli""" + + parser = argparse.ArgumentParser(description="Lorax Composer commandline tool", + epilog=epilog, + formatter_class=argparse.RawDescriptionHelpFormatter, + fromfile_prefix_chars="@") + + parser.add_argument("-j", "--json", action="store_true", default=False, + help="Output the raw JSON response instead of the normal output.") + parser.add_argument("-s", "--socket", default="/run/weldr/api.socket", metavar="SOCKET", + help="Path to the socket file to listen on") + parser.add_argument("--log", dest="logfile", default=None, metavar="LOG", + help="Path to logfile (./composer-cli.log)") + parser.add_argument("-a", "--api", dest="api_version", default="0", metavar="APIVER", + help="API Version to use") + parser.add_argument("--test", dest="testmode", default=0, type=int, metavar="TESTMODE", + help="Pass test mode to compose. 1=Mock compose with fail. 2=Mock compose with finished.") + parser.add_argument("-V", action="store_true", dest="showver", + help="show program's version number and exit") + + # Commands are implemented by parsing the remaining arguments outside of argparse + parser.add_argument('args', nargs=argparse.REMAINDER) + + return parser
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/compose.html b/f29-branch/_modules/composer/cli/compose.html new file mode 100644 index 00000000..3572d07b --- /dev/null +++ b/f29-branch/_modules/composer/cli/compose.html @@ -0,0 +1,731 @@ + + + + + + + + + + + composer.cli.compose — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.compose

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+from datetime import datetime
+import sys
+import json
+
+from composer import http_client as client
+from composer.cli.help import compose_help
+from composer.cli.utilities import argify, handle_api_result, packageNEVRA
+
+
[docs]def compose_cmd(opts): + """Process compose commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + + This dispatches the compose commands to a function + """ + cmd_map = { + "list": compose_list, + "status": compose_status, + "types": compose_types, + "start": compose_start, + "log": compose_log, + "cancel": compose_cancel, + "delete": compose_delete, + "info": compose_info, + "metadata": compose_metadata, + "results": compose_results, + "logs": compose_logs, + "image": compose_image, + } + if opts.args[1] == "help" or opts.args[1] == "--help": + print(compose_help) + return 0 + elif opts.args[1] not in cmd_map: + log.error("Unknown compose command: %s", opts.args[1]) + return 1 + + return cmd_map[opts.args[1]](opts.socket, opts.api_version, opts.args[2:], opts.json, opts.testmode)
+ +
[docs]def compose_list(socket_path, api_version, args, show_json=False, testmode=0): + """Return a simple list of compose identifiers""" + + states = ("running", "waiting", "finished", "failed") + + which = set() + + if any(a not in states for a in args): + # TODO: error about unknown state + return 1 + elif not args: + which.update(states) + else: + which.update(args) + + results = [] + + if "running" in which or "waiting" in which: + api_route = client.api_url(api_version, "/compose/queue") + r = client.get_url_json(socket_path, api_route) + if "running" in which: + results += r["run"] + if "waiting" in which: + results += r["new"] + + if "finished" in which: + api_route = client.api_url(api_version, "/compose/finished") + r = client.get_url_json(socket_path, api_route) + results += r["finished"] + + if "failed" in which: + api_route = client.api_url(api_version, "/compose/failed") + r = client.get_url_json(socket_path, api_route) + results += r["failed"] + + if results: + if show_json: + print(json.dumps(results, indent=4)) + else: + list_fmt = "{id} {queue_status} {blueprint} {version} {compose_type}" + print("\n".join(list_fmt.format(**c) for c in results)) + + return 0
+ +
[docs]def compose_status(socket_path, api_version, args, show_json=False, testmode=0): + """Return the status of all known composes + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + This doesn't map directly to an API command, it combines the results from queue, finished, + and failed so raw JSON output is not available. + """ + def get_status(compose): + return {"id": compose["id"], + "blueprint": compose["blueprint"], + "version": compose["version"], + "compose_type": compose["compose_type"], + "image_size": compose["image_size"], + "status": compose["queue_status"], + "created": compose.get("job_created"), + "started": compose.get("job_started"), + "finished": compose.get("job_finished")} + + # Sort the status in a specific order + def sort_status(a): + order = ["RUNNING", "WAITING", "FINISHED", "FAILED"] + return (order.index(a["status"]), a["blueprint"], a["version"], a["compose_type"]) + + status = [] + + # Get the composes currently in the queue + api_route = client.api_url(api_version, "/compose/queue") + result = client.get_url_json(socket_path, api_route) + status.extend(list(map(get_status, result["run"] + result["new"]))) + + # Get the list of finished composes + api_route = client.api_url(api_version, "/compose/finished") + result = client.get_url_json(socket_path, api_route) + status.extend(list(map(get_status, result["finished"]))) + + # Get the list of failed composes + api_route = client.api_url(api_version, "/compose/failed") + result = client.get_url_json(socket_path, api_route) + status.extend(list(map(get_status, result["failed"]))) + + # Sort them by status (running, waiting, finished, failed) and then by name and version. + status.sort(key=sort_status) + + if show_json: + print(json.dumps(status, indent=4)) + return 0 + + # Print them as UUID blueprint STATUS + for c in status: + if c["image_size"] > 0: + image_size = str(c["image_size"]) + else: + image_size = "" + + dt = datetime.fromtimestamp(c.get("finished") or c.get("started") or c.get("created")) + + print("%s %-8s %s %-15s %s %-16s %s" % (c["id"], c["status"], dt.strftime("%c"), c["blueprint"], + c["version"], c["compose_type"], image_size))
+ + +
[docs]def compose_types(socket_path, api_version, args, show_json=False, testmode=0): + """Return information about the supported compose types + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + Add additional details to types that are known to composer-cli. Raw JSON output does not + include this extra information. + """ + api_route = client.api_url(api_version, "/compose/types") + result = client.get_url_json(socket_path, api_route) + if show_json: + print(json.dumps(result, indent=4)) + return 0 + + # output a plain list of identifiers, one per line + print("\n".join(t["name"] for t in result["types"]))
+ +
[docs]def compose_start(socket_path, api_version, args, show_json=False, testmode=0): + """Start a new compose using the selected blueprint and type + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: Set to 1 to simulate a failed compose, set to 2 to simulate a finished one. + :type testmode: int + + compose start <blueprint-name> <compose-type> + """ + if len(args) == 0: + log.error("start is missing the blueprint name and output type") + return 1 + if len(args) == 1: + log.error("start is missing the output type") + return 1 + + config = { + "blueprint_name": args[0], + "compose_type": args[1], + "branch": "master" + } + if testmode: + test_url = "?test=%d" % testmode + else: + test_url = "" + api_route = client.api_url(api_version, "/compose" + test_url) + result = client.post_url_json(socket_path, api_route, json.dumps(config)) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + print("Compose %s added to the queue" % result["build_id"]) + return rc
+ +
[docs]def compose_log(socket_path, api_version, args, show_json=False, testmode=0): + """Show the last part of the compose log + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose log <uuid> [<size>kB] + + This will display the last 1kB of the compose's log file. Can be used to follow progress + during the build. + """ + if len(args) == 0: + log.error("log is missing the compose build id") + return 1 + if len(args) == 2: + try: + log_size = int(args[1]) + except ValueError: + log.error("Log size must be an integer.") + return 1 + else: + log_size = 1024 + + api_route = client.api_url(api_version, "/compose/log/%s?size=%d" % (args[0], log_size)) + try: + result = client.get_url_raw(socket_path, api_route) + except RuntimeError as e: + print(str(e)) + return 1 + + print(result) + return 0
+ +
[docs]def compose_cancel(socket_path, api_version, args, show_json=False, testmode=0): + """Cancel a running compose + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose cancel <uuid> + + This will cancel a running compose. It does nothing if the compose has finished. + """ + if len(args) == 0: + log.error("cancel is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/cancel/%s" % args[0]) + result = client.delete_url_json(socket_path, api_route) + return handle_api_result(result, show_json)[0]
+ +
[docs]def compose_delete(socket_path, api_version, args, show_json=False, testmode=0): + """Delete a finished compose's results + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose delete <uuid,...> + + Delete the listed compose results. It will only delete results for composes that have finished + or failed, not a running compose. + """ + if len(args) == 0: + log.error("delete is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/delete/%s" % (",".join(argify(args)))) + result = client.delete_url_json(socket_path, api_route) + return handle_api_result(result, show_json)[0]
+ +
[docs]def compose_info(socket_path, api_version, args, show_json=False, testmode=0): + """Return detailed information about the compose + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose info <uuid> + + This returns information about the compose, including the blueprint and the dependencies. + """ + if len(args) == 0: + log.error("info is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/info/%s" % args[0]) + result = client.get_url_json(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + if result["image_size"] > 0: + image_size = str(result["image_size"]) + else: + image_size = "" + + + print("%s %-8s %-15s %s %-16s %s" % (result["id"], + result["queue_status"], + result["blueprint"]["name"], + result["blueprint"]["version"], + result["compose_type"], + image_size)) + print("Packages:") + for p in result["blueprint"]["packages"]: + print(" %s-%s" % (p["name"], p["version"])) + + print("Modules:") + for m in result["blueprint"]["modules"]: + print(" %s-%s" % (m["name"], m["version"])) + + print("Dependencies:") + for d in result["deps"]["packages"]: + print(" " + packageNEVRA(d)) + + return rc
+ +
[docs]def compose_metadata(socket_path, api_version, args, show_json=False, testmode=0): + """Download a tar file of the compose's metadata + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose metadata <uuid> + + Saves the metadata as uuid-metadata.tar + """ + if len(args) == 0: + log.error("metadata is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/metadata/%s" % args[0]) + try: + rc = client.download_file(socket_path, api_route) + except RuntimeError as e: + print(str(e)) + rc = 1 + + return rc
+ +
[docs]def compose_results(socket_path, api_version, args, show_json=False, testmode=0): + """Download a tar file of the compose's results + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose results <uuid> + + The results includes the metadata, output image, and logs. + It is saved as uuid.tar + """ + if len(args) == 0: + log.error("results is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/results/%s" % args[0]) + try: + rc = client.download_file(socket_path, api_route, sys.stdout.isatty()) + except RuntimeError as e: + print(str(e)) + rc = 1 + + return rc
+ +
[docs]def compose_logs(socket_path, api_version, args, show_json=False, testmode=0): + """Download a tar of the compose's logs + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose logs <uuid> + + Saves the logs as uuid-logs.tar + """ + if len(args) == 0: + log.error("logs is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/logs/%s" % args[0]) + try: + rc = client.download_file(socket_path, api_route, sys.stdout.isatty()) + except RuntimeError as e: + print(str(e)) + rc = 1 + + return rc
+ +
[docs]def compose_image(socket_path, api_version, args, show_json=False, testmode=0): + """Download the compose's output image + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + :param testmode: unused in this function + :type testmode: int + + compose image <uuid> + + This downloads only the result image, saving it as the image name, which depends on the type + of compose that was selected. + """ + if len(args) == 0: + log.error("logs is missing the compose build id") + return 1 + + api_route = client.api_url(api_version, "/compose/image/%s" % args[0]) + try: + rc = client.download_file(socket_path, api_route, sys.stdout.isatty()) + except RuntimeError as e: + print(str(e)) + rc = 1 + + return rc
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/modules.html b/f29-branch/_modules/composer/cli/modules.html new file mode 100644 index 00000000..af141cf6 --- /dev/null +++ b/f29-branch/_modules/composer/cli/modules.html @@ -0,0 +1,265 @@ + + + + + + + + + + + composer.cli.modules — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.modules

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+from composer import http_client as client
+from composer.cli.help import modules_help
+from composer.cli.utilities import handle_api_result
+
+
[docs]def modules_cmd(opts): + """Process modules commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + """ + if opts.args[1] == "help" or opts.args[1] == "--help": + print(modules_help) + return 0 + elif opts.args[1] != "list": + log.error("Unknown modules command: %s", opts.args[1]) + return 1 + + api_route = client.api_url(opts.api_version, "/modules/list") + result = client.get_url_json_unlimited(opts.socket, api_route) + (rc, exit_now) = handle_api_result(result, opts.json) + if exit_now: + return rc + + # "list" should output a plain list of identifiers, one per line. + print("\n".join(r["name"] for r in result["modules"])) + + return rc
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/projects.html b/f29-branch/_modules/composer/cli/projects.html new file mode 100644 index 00000000..10e9c3e5 --- /dev/null +++ b/f29-branch/_modules/composer/cli/projects.html @@ -0,0 +1,327 @@ + + + + + + + + + + + composer.cli.projects — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.projects

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import textwrap
+
+from composer import http_client as client
+from composer.cli.help import projects_help
+from composer.cli.utilities import handle_api_result
+
+
[docs]def projects_cmd(opts): + """Process projects commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + """ + cmd_map = { + "list": projects_list, + "info": projects_info, + } + if opts.args[1] == "help" or opts.args[1] == "--help": + print(projects_help) + return 0 + elif opts.args[1] not in cmd_map: + log.error("Unknown projects command: %s", opts.args[1]) + return 1 + + return cmd_map[opts.args[1]](opts.socket, opts.api_version, opts.args[2:], opts.json)
+ +
[docs]def projects_list(socket_path, api_version, args, show_json=False): + """Output the list of available projects + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + projects list + """ + api_route = client.api_url(api_version, "/projects/list") + result = client.get_url_json_unlimited(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + for proj in result["projects"]: + for k in [field for field in ("name", "summary", "homepage", "description") if proj[field]]: + print("%s: %s" % (k.title(), textwrap.fill(proj[k], subsequent_indent=" " * (len(k)+2)))) + print("\n\n") + + return rc
+ +
[docs]def projects_info(socket_path, api_version, args, show_json=False): + """Output info on a list of projects + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + projects info <project,...> + """ + if len(args) == 0: + log.error("projects info is missing the packages") + return 1 + + api_route = client.api_url(api_version, "/projects/info/%s" % ",".join(args)) + result = client.get_url_json(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + for proj in result["projects"]: + for k in [field for field in ("name", "summary", "homepage", "description") if proj[field]]: + print("%s: %s" % (k.title(), textwrap.fill(proj[k], subsequent_indent=" " * (len(k)+2)))) + print("Builds: ") + for build in proj["builds"]: + print(" %s%s-%s.%s at %s for %s" % ("" if not build["epoch"] else str(build["epoch"]) + ":", + build["source"]["version"], + build["release"], + build["arch"], + build["build_time"], + build["changelog"])) + print("") + return rc
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/sources.html b/f29-branch/_modules/composer/cli/sources.html new file mode 100644 index 00000000..39e02095 --- /dev/null +++ b/f29-branch/_modules/composer/cli/sources.html @@ -0,0 +1,369 @@ + + + + + + + + + + + composer.cli.sources — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.sources

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import os
+
+from composer import http_client as client
+from composer.cli.help import sources_help
+from composer.cli.utilities import argify, handle_api_result
+
+
[docs]def sources_cmd(opts): + """Process sources commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + """ + cmd_map = { + "list": sources_list, + "info": sources_info, + "add": sources_add, + "change": sources_add, + "delete": sources_delete, + } + if opts.args[1] == "help" or opts.args[1] == "--help": + print(sources_help) + return 0 + elif opts.args[1] not in cmd_map: + log.error("Unknown sources command: %s", opts.args[1]) + return 1 + + return cmd_map[opts.args[1]](opts.socket, opts.api_version, opts.args[2:], opts.json)
+ +
[docs]def sources_list(socket_path, api_version, args, show_json=False): + """Output the list of available sources + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + sources list + """ + api_route = client.api_url(api_version, "/projects/source/list") + result = client.get_url_json(socket_path, api_route) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + # "list" should output a plain list of identifiers, one per line. + print("\n".join(result["sources"])) + return rc
+ +
[docs]def sources_info(socket_path, api_version, args, show_json=False): + """Output info on a list of projects + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + sources info <source-name> + """ + if len(args) == 0: + log.error("sources info is missing the name of the source") + return 1 + + if show_json: + api_route = client.api_url(api_version, "/projects/source/info/%s" % ",".join(args)) + result = client.get_url_json(socket_path, api_route) + rc = handle_api_result(result, show_json)[0] + else: + api_route = client.api_url(api_version, "/projects/source/info/%s?format=toml" % ",".join(args)) + try: + result = client.get_url_raw(socket_path, api_route) + print(result) + rc = 0 + except RuntimeError as e: + print(str(e)) + rc = 1 + + return rc
+ +
[docs]def sources_add(socket_path, api_version, args, show_json=False): + """Add or change a source + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + sources add <source.toml> + """ + api_route = client.api_url(api_version, "/projects/source/new") + rval = 0 + for source in argify(args): + if not os.path.exists(source): + log.error("Missing source file: %s", source) + continue + source_toml = open(source, "r").read() + + result = client.post_url_toml(socket_path, api_route, source_toml) + if handle_api_result(result, show_json)[0]: + rval = 1 + return rval
+ +
[docs]def sources_delete(socket_path, api_version, args, show_json=False): + """Delete a source + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param api_version: Version of the API to talk to. eg. "0" + :type api_version: str + :param args: List of remaining arguments from the cmdline + :type args: list of str + :param show_json: Set to True to show the JSON output instead of the human readable output + :type show_json: bool + + sources delete <source-name> + """ + api_route = client.api_url(api_version, "/projects/source/delete/%s" % args[0]) + result = client.delete_url_json(socket_path, api_route) + + return handle_api_result(result, show_json)[0]
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/status.html b/f29-branch/_modules/composer/cli/status.html new file mode 100644 index 00000000..376fe43d --- /dev/null +++ b/f29-branch/_modules/composer/cli/status.html @@ -0,0 +1,273 @@ + + + + + + + + + + + composer.cli.status — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.status

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+from composer import http_client as client
+from composer.cli.help import status_help
+from composer.cli.utilities import handle_api_result
+
+
[docs]def status_cmd(opts): + """Process status commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + """ + if opts.args[1] == "help" or opts.args[1] == "--help": + print(status_help) + return 0 + elif opts.args[1] != "show": + log.error("Unknown status command: %s", opts.args[1]) + return 1 + + result = client.get_url_json(opts.socket, "/api/status") + (rc, exit_now) = handle_api_result(result, opts.json) + if exit_now: + return rc + + print("API server status:") + print(" Database version: " + result["db_version"]) + print(" Database supported: %s" % result["db_supported"]) + print(" Schema version: " + result["schema_version"]) + print(" API version: " + result["api"]) + print(" Backend: " + result["backend"]) + print(" Build: " + result["build"]) + + if result["msgs"]: + print("Error messages:") + print("\n".join([" " + r for r in result["msgs"]])) + + return rc
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/cli/utilities.html b/f29-branch/_modules/composer/cli/utilities.html new file mode 100644 index 00000000..77d1fb23 --- /dev/null +++ b/f29-branch/_modules/composer/cli/utilities.html @@ -0,0 +1,312 @@ + + + + + + + + + + + composer.cli.utilities — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.utilities

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import json
+
+
[docs]def argify(args): + """Take a list of human args and return a list with each item + + :param args: list of strings with possible commas and spaces + :type args: list of str + :returns: List of all the items + :rtype: list of str + + Examples: + + ["one,two", "three", ",four", ",five,"] returns ["one", "two", "three", "four", "five"] + """ + return [i for i in [arg for entry in args for arg in entry.split(",")] if i]
+ +
[docs]def toml_filename(blueprint_name): + """Convert a blueprint name into a filename.toml + + :param blueprint_name: The blueprint's name + :type blueprint_name: str + :returns: The blueprint name with ' ' converted to - and .toml appended + :rtype: str + """ + return blueprint_name.replace(" ", "-") + ".toml"
+ +
[docs]def frozen_toml_filename(blueprint_name): + """Convert a blueprint name into a filename.toml + + :param blueprint_name: The blueprint's name + :type blueprint_name: str + :returns: The blueprint name with ' ' converted to - and .toml appended + :rtype: str + """ + return blueprint_name.replace(" ", "-") + ".frozen.toml"
+ +
[docs]def handle_api_result(result, show_json=False): + """Log any errors, return the correct value + + :param result: JSON result from the http query + :type result: dict + :rtype: tuple + :returns: (rc, should_exit_now) + + Return the correct rc for the program (0 or 1), and whether or + not to continue processing the results. + """ + if show_json: + print(json.dumps(result, indent=4)) + else: + for err in result.get("errors", []): + log.error(err["msg"]) + + # What's the rc? If status is present, use that + # If not, use length of errors + if "status" in result: + rc = bool(not result["status"]) + else: + rc = bool(len(result.get("errors", [])) > 0) + + # Caller should return if showing json, or status was present and False + exit_now = show_json or ("status" in result and rc) + return (rc, exit_now)
+ +
[docs]def packageNEVRA(pkg): + """Return the package info as a NEVRA + + :param pkg: The package details + :type pkg: dict + :returns: name-[epoch:]version-release-arch + :rtype: str + """ + if pkg["epoch"]: + return "%s-%s:%s-%s.%s" % (pkg["name"], pkg["epoch"], pkg["version"], pkg["release"], pkg["arch"]) + else: + return "%s-%s-%s.%s" % (pkg["name"], pkg["version"], pkg["release"], pkg["arch"])
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/http_client.html b/f29-branch/_modules/composer/http_client.html new file mode 100644 index 00000000..225e141e --- /dev/null +++ b/f29-branch/_modules/composer/http_client.html @@ -0,0 +1,475 @@ + + + + + + + + + + + composer.http_client — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.http_client

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import os
+import sys
+import json
+from urllib.parse import urlparse, urlunparse
+
+from composer.unix_socket import UnixHTTPConnectionPool
+
+
[docs]def api_url(api_version, url): + """Return the versioned path to the API route + + :param api_version: The version of the API to talk to. eg. "0" + :type api_version: str + :param url: The API route to talk to + :type url: str + :returns: The full url to use for the route and API version + :rtype: str + """ + return os.path.normpath("/api/v%s/%s" % (api_version, url))
+ +
[docs]def append_query(url, query): + """Add a query argument to a URL + + The query should be of the form "param1=what&param2=ever", i.e., no + leading '?'. The new query data will be appended to any existing + query string. + + :param url: The original URL + :type url: str + :param query: The query to append + :type query: str + :returns: The new URL with the query argument included + :rtype: str + """ + + url_parts = urlparse(url) + if url_parts.query: + new_query = url_parts.query + "&" + query + else: + new_query = query + return urlunparse([url_parts[0], url_parts[1], url_parts[2], + url_parts[3], new_query, url_parts[5]])
+ +
[docs]def get_url_raw(socket_path, url): + """Return the raw results of a GET request + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to request + :type url: str + :returns: The raw response from the server + :rtype: str + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("GET", url) + if r.status == 400: + err = json.loads(r.data.decode("utf-8")) + if "status" in err and err["status"] == False: + msgs = [e["msg"] for e in err["errors"]] + raise RuntimeError(", ".join(msgs)) + + return r.data.decode('utf-8')
+ +
[docs]def get_url_json(socket_path, url): + """Return the JSON results of a GET request + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to request + :type url: str + :returns: The json response from the server + :rtype: dict + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("GET", url) + return json.loads(r.data.decode('utf-8'))
+ +
[docs]def get_url_json_unlimited(socket_path, url, total_fn=None): + """Return the JSON results of a GET request + + For URLs that use offset/limit arguments, this command will + fetch all results for the given request. + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to request + :type url: str + :returns: The json response from the server + :rtype: dict + """ + def default_total_fn(data): + """Return the total number of available results""" + return data["total"] + + http = UnixHTTPConnectionPool(socket_path) + + # Start with limit=0 to just get the number of objects + total_url = append_query(url, "limit=0") + r_total = http.request("GET", total_url) + json_total = json.loads(r_total.data.decode('utf-8')) + + # Where to get the total from + if not total_fn: + total_fn = default_total_fn + + # Add the "total" returned by limit=0 as the new limit + unlimited_url = append_query(url, "limit=%d" % total_fn(json_total)) + r_unlimited = http.request("GET", unlimited_url) + return json.loads(r_unlimited.data.decode('utf-8'))
+ +
[docs]def delete_url_json(socket_path, url): + """Send a DELETE request to the url and return JSON response + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to send DELETE to + :type url: str + :returns: The json response from the server + :rtype: dict + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("DELETE", url) + return json.loads(r.data.decode("utf-8"))
+ +
[docs]def post_url(socket_path, url, body): + """POST raw data to the URL + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to send POST to + :type url: str + :param body: The data for the body of the POST + :type body: str + :returns: The json response from the server + :rtype: dict + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("POST", url, + body=body.encode("utf-8")) + return json.loads(r.data.decode("utf-8"))
+ +
[docs]def post_url_toml(socket_path, url, body): + """POST a TOML string to the URL + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to send POST to + :type url: str + :param body: The data for the body of the POST + :type body: str + :returns: The json response from the server + :rtype: dict + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("POST", url, + body=body.encode("utf-8"), + headers={"Content-Type": "text/x-toml"}) + return json.loads(r.data.decode("utf-8"))
+ +
[docs]def post_url_json(socket_path, url, body): + """POST some JSON data to the URL + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to send POST to + :type url: str + :param body: The data for the body of the POST + :type body: str + :returns: The json response from the server + :rtype: dict + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("POST", url, + body=body.encode("utf-8"), + headers={"Content-Type": "application/json"}) + return json.loads(r.data.decode("utf-8"))
+ +
[docs]def get_filename(headers): + """Get the filename from the response header + + :param response: The urllib3 response object + :type response: Response + :raises: RuntimeError if it cannot find a filename in the header + :returns: Filename from content-disposition header + :rtype: str + """ + log.debug("Headers = %s", headers) + if "content-disposition" not in headers: + raise RuntimeError("No Content-Disposition header; cannot get filename") + + try: + k, _, v = headers["content-disposition"].split(";")[1].strip().partition("=") + if k != "filename": + raise RuntimeError("No filename= found in content-disposition header") + except RuntimeError: + raise + except Exception as e: + raise RuntimeError("Error parsing filename from content-disposition header: %s" % str(e)) + + return os.path.basename(v)
+ +
[docs]def download_file(socket_path, url, progress=True): + """Download a file, saving it to the CWD with the included filename + + :param socket_path: Path to the Unix socket to use for API communication + :type socket_path: str + :param url: URL to send POST to + :type url: str + """ + http = UnixHTTPConnectionPool(socket_path) + r = http.request("GET", url, preload_content=False) + if r.status == 400: + err = json.loads(r.data.decode("utf-8")) + if not err["status"]: + msgs = [e["msg"] for e in err["errors"]] + raise RuntimeError(", ".join(msgs)) + + filename = get_filename(r.headers) + if os.path.exists(filename): + msg = "%s exists, skipping download" % filename + log.error(msg) + raise RuntimeError(msg) + + with open(filename, "wb") as f: + while True: + data = r.read(10 * 1024**2) + if not data: + break + f.write(data) + + if progress: + data_written = f.tell() + if data_written > 5 * 1024**2: + sys.stdout.write("%s: %0.2f MB \r" % (filename, data_written / 1024**2)) + else: + sys.stdout.write("%s: %0.2f kB\r" % (filename, data_written / 1024)) + sys.stdout.flush() + + print("") + r.release_conn() + + return 0
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/composer/unix_socket.html b/f29-branch/_modules/composer/unix_socket.html new file mode 100644 index 00000000..1c89cff6 --- /dev/null +++ b/f29-branch/_modules/composer/unix_socket.html @@ -0,0 +1,276 @@ + + + + + + + + + + + composer.unix_socket — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.unix_socket

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+import http.client
+import socket
+import urllib3
+
+
+# These 2 classes were adapted and simplified for use with just urllib3.
+# Originally from https://github.com/msabramo/requests-unixsocket/blob/master/requests_unixsocket/adapters.py
+
+# The following was adapted from some code from docker-py
+# https://github.com/docker/docker-py/blob/master/docker/transport/unixconn.py
+
[docs]class UnixHTTPConnection(http.client.HTTPConnection, object): + + def __init__(self, socket_path, timeout=60): + """Create an HTTP connection to a unix domain socket + + :param socket_path: The path to the Unix domain socket + :param timeout: Number of seconds to timeout the connection + """ + super(UnixHTTPConnection, self).__init__('localhost', timeout=timeout) + self.socket_path = socket_path + self.sock = None + + def __del__(self): # base class does not have d'tor + if self.sock: + self.sock.close() + +
[docs] def connect(self): + sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) + sock.settimeout(self.timeout) + sock.connect(self.socket_path) + self.sock = sock
+ +
[docs]class UnixHTTPConnectionPool(urllib3.connectionpool.HTTPConnectionPool): + + def __init__(self, socket_path, timeout=60): + """Create a connection pool using a Unix domain socket + + :param socket_path: The path to the Unix domain socket + :param timeout: Number of seconds to timeout the connection + """ + super(UnixHTTPConnectionPool, self).__init__('localhost', timeout=timeout) + self.socket_path = socket_path + + def _new_conn(self): + return UnixHTTPConnection(self.socket_path, self.timeout)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/index.html b/f29-branch/_modules/index.html new file mode 100644 index 00000000..c6beba6b --- /dev/null +++ b/f29-branch/_modules/index.html @@ -0,0 +1,257 @@ + + + + + + + + + + + Overview: module code — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax.html b/f29-branch/_modules/pylorax.html new file mode 100644 index 00000000..3bbb8c70 --- /dev/null +++ b/f29-branch/_modules/pylorax.html @@ -0,0 +1,679 @@ + + + + + + + + + + + pylorax — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax

+#
+# __init__.py
+#
+# Copyright (C) 2010-2015  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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#                     David Cantrell <dcantrell@redhat.com>
+#                     Will Woods <wwoods@redhat.com>
+
+# set up logging
+import logging
+logger = logging.getLogger("pylorax")
+logger.addHandler(logging.NullHandler())
+
+program_log = logging.getLogger("program")
+
+import sys
+import os
+import configparser
+import tempfile
+import locale
+from subprocess import CalledProcessError
+import selinux
+from glob import glob
+
+from pylorax.base import BaseLoraxClass, DataHolder
+import pylorax.output as output
+
+import dnf
+
+from pylorax.sysutils import joinpaths, remove, linktree
+
+from pylorax.treebuilder import RuntimeBuilder, TreeBuilder
+from pylorax.buildstamp import BuildStamp
+from pylorax.treeinfo import TreeInfo
+from pylorax.discinfo import DiscInfo
+from pylorax.executils import runcmd, runcmd_output
+
+
+# get lorax version
+try:
+    import pylorax.version
+except ImportError:
+    vernum = "devel"
+else:
+    vernum = pylorax.version.num
+
+DRACUT_DEFAULT = ["--xz", "--install", "/.buildstamp", "--no-early-microcode", "--add", "fips"]
+
+# List of drivers to remove on ppc64 arch to keep initrd < 32MiB
+REMOVE_PPC64_DRIVERS = "floppy scsi_debug nouveau radeon cirrus mgag200"
+REMOVE_PPC64_MODULES = "drm plymouth"
+
+# Used for DNF conf.module_platform_id
+DEFAULT_PLATFORM_ID = "platform:f29"
+
+
[docs]class ArchData(DataHolder): + lib64_arches = ("x86_64", "ppc64", "ppc64le", "s390x", "ia64", "aarch64") + bcj_arch = dict(i386="x86", x86_64="x86", + ppc="powerpc", ppc64="powerpc", ppc64le="powerpc", + arm="arm", armhfp="arm") + + def __init__(self, buildarch): + super(ArchData, self).__init__() + self.buildarch = buildarch + self.basearch = dnf.rpm.basearch(buildarch) + self.libdir = "lib64" if self.basearch in self.lib64_arches else "lib" + self.bcj = self.bcj_arch.get(self.basearch)
+ +
[docs]class Lorax(BaseLoraxClass): + + def __init__(self): + BaseLoraxClass.__init__(self) + self._configured = False + self.product = None + self.workdir = None + self.arch = None + self.conf = None + self.inroot = None + self.debug = False + self.outputdir = None + self._templatedir = None + + # set locale to C + locale.setlocale(locale.LC_ALL, 'C') + +
[docs] def configure(self, conf_file="/etc/lorax/lorax.conf"): + self.conf = configparser.SafeConfigParser() + + # set defaults + self.conf.add_section("lorax") + self.conf.set("lorax", "debug", "1") + self.conf.set("lorax", "sharedir", "/usr/share/lorax") + self.conf.set("lorax", "logdir", "/var/log/lorax") + + self.conf.add_section("output") + self.conf.set("output", "colors", "1") + self.conf.set("output", "encoding", "utf-8") + self.conf.set("output", "ignorelist", "/usr/share/lorax/ignorelist") + + self.conf.add_section("templates") + self.conf.set("templates", "ramdisk", "ramdisk.ltmpl") + + self.conf.add_section("compression") + self.conf.set("compression", "type", "xz") + self.conf.set("compression", "args", "") + self.conf.set("compression", "bcj", "on") + + # read the config file + if os.path.isfile(conf_file): + self.conf.read(conf_file) + + # set up the output + self.debug = self.conf.getboolean("lorax", "debug") + output_level = output.DEBUG if self.debug else output.INFO + + if sys.stdout.isatty(): + colors = self.conf.getboolean("output", "colors") + else: + colors = False + encoding = self.conf.get("output", "encoding") + + self.output.basic_config(output_level=output_level, + colors=colors, encoding=encoding) + + ignorelist = self.conf.get("output", "ignorelist") + if os.path.isfile(ignorelist): + with open(ignorelist, "r") as fobj: + for line in fobj: + line = line.strip() + if line and not line.startswith("#"): + self.output.ignore(line) + + # cron does not have sbin in PATH, + # so we have to add it ourselves + os.environ["PATH"] = "{0}:/sbin:/usr/sbin".format(os.environ["PATH"]) + + # remove some environmental variables that can cause problems with package scripts + env_remove = ('DISPLAY', 'DBUS_SESSION_BUS_ADDRESS') + list(os.environ.pop(k) for k in env_remove if k in os.environ) + + self._configured = True
+ + @property + def templatedir(self): + """Find the template directory. + + Pick the first directory under sharedir/templates.d/ if it exists. + Otherwise use the sharedir + """ + if not self._templatedir: + self._templatedir = find_templates(self.conf.get("lorax", "sharedir")) + logger.info("Using templatedir %s", self._templatedir) + return self._templatedir + +
[docs] def init_stream_logging(self): + sh = logging.StreamHandler() + sh.setLevel(logging.INFO) + logger.addHandler(sh)
+ +
[docs] def init_file_logging(self, logdir, logname="pylorax.log"): + fh = logging.FileHandler(filename=joinpaths(logdir, logname), mode="w") + fh.setLevel(logging.DEBUG) + logger.addHandler(fh)
+ +
[docs] def run(self, dbo, product, version, release, variant="", bugurl="", + isfinal=False, workdir=None, outputdir=None, buildarch=None, volid=None, + domacboot=True, doupgrade=True, remove_temp=False, + installpkgs=None, excludepkgs=None, + size=2, + add_templates=None, + add_template_vars=None, + add_arch_templates=None, + add_arch_template_vars=None, + verify=True, + user_dracut_args=None, + squashfs_only=False): + + assert self._configured + + installpkgs = installpkgs or [] + excludepkgs = excludepkgs or [] + + if domacboot: + try: + runcmd(["rpm", "-q", "hfsplus-tools"]) + except CalledProcessError: + logger.critical("you need to install hfsplus-tools to create mac images") + sys.exit(1) + + # set up work directory + self.workdir = workdir or tempfile.mkdtemp(prefix="pylorax.work.") + if not os.path.isdir(self.workdir): + os.makedirs(self.workdir) + + # set up log directory + logdir = self.conf.get("lorax", "logdir") + if not os.path.isdir(logdir): + os.makedirs(logdir) + + self.init_stream_logging() + self.init_file_logging(logdir) + + logger.debug("version is %s", vernum) + log_selinux_state() + + logger.debug("using work directory %s", self.workdir) + logger.debug("using log directory %s", logdir) + + # set up output directory + self.outputdir = outputdir or tempfile.mkdtemp(prefix="pylorax.out.") + if not os.path.isdir(self.outputdir): + os.makedirs(self.outputdir) + logger.debug("using output directory %s", self.outputdir) + + # do we have root privileges? + logger.info("checking for root privileges") + if not os.geteuid() == 0: + logger.critical("no root privileges") + sys.exit(1) + + # do we have a proper dnf base object? + logger.info("checking dnf base object") + if not isinstance(dbo, dnf.Base): + logger.critical("no dnf base object") + sys.exit(1) + self.inroot = dbo.conf.installroot + logger.debug("using install root: %s", self.inroot) + + if not buildarch: + buildarch = get_buildarch(dbo) + + logger.info("setting up build architecture") + self.arch = ArchData(buildarch) + for attr in ('buildarch', 'basearch', 'libdir'): + logger.debug("self.arch.%s = %s", attr, getattr(self.arch,attr)) + + logger.info("setting up build parameters") + self.product = DataHolder(name=product, version=version, release=release, + variant=variant, bugurl=bugurl, isfinal=isfinal) + logger.debug("product data: %s", self.product) + + # NOTE: if you change isolabel, you need to change pungi to match, or + # the pungi images won't boot. + isolabel = volid or "%s-%s-%s" % (self.product.name, self.product.version, self.arch.basearch) + + if len(isolabel) > 32: + logger.fatal("the volume id cannot be longer than 32 characters") + sys.exit(1) + + # NOTE: rb.root = dbo.conf.installroot (== self.inroot) + rb = RuntimeBuilder(product=self.product, arch=self.arch, + dbo=dbo, templatedir=self.templatedir, + installpkgs=installpkgs, + excludepkgs=excludepkgs, + add_templates=add_templates, + add_template_vars=add_template_vars) + + logger.info("installing runtime packages") + rb.install() + + # write .buildstamp + buildstamp = BuildStamp(self.product.name, self.product.version, + self.product.bugurl, self.product.isfinal, + self.arch.buildarch, self.product.variant) + + buildstamp.write(joinpaths(self.inroot, ".buildstamp")) + + if self.debug: + rb.writepkglists(joinpaths(logdir, "pkglists")) + rb.writepkgsizes(joinpaths(logdir, "original-pkgsizes.txt")) + + logger.info("doing post-install configuration") + rb.postinstall() + + # write .discinfo + discinfo = DiscInfo(self.product.release, self.arch.basearch) + discinfo.write(joinpaths(self.outputdir, ".discinfo")) + + logger.info("backing up installroot") + installroot = joinpaths(self.workdir, "installroot") + linktree(self.inroot, installroot) + + logger.info("generating kernel module metadata") + rb.generate_module_data() + + logger.info("cleaning unneeded files") + rb.cleanup() + + if verify: + logger.info("verifying the installroot") + if not rb.verify(): + sys.exit(1) + else: + logger.info("Skipping verify") + + if self.debug: + rb.writepkgsizes(joinpaths(logdir, "final-pkgsizes.txt")) + + logger.info("creating the runtime image") + runtime = "images/install.img" + compression = self.conf.get("compression", "type") + compressargs = self.conf.get("compression", "args").split() # pylint: disable=no-member + if self.conf.getboolean("compression", "bcj"): + if self.arch.bcj: + compressargs += ["-Xbcj", self.arch.bcj] + else: + logger.info("no BCJ filter for arch %s", self.arch.basearch) + if squashfs_only: + # Create an ext4 rootfs.img and compress it with squashfs + rb.create_squashfs_runtime(joinpaths(installroot,runtime), + compression=compression, compressargs=compressargs, + size=size) + else: + # Create an ext4 rootfs.img and compress it with squashfs + rb.create_ext4_runtime(joinpaths(installroot,runtime), + compression=compression, compressargs=compressargs, + size=size) + rb.finished() + + logger.info("preparing to build output tree and boot images") + treebuilder = TreeBuilder(product=self.product, arch=self.arch, + inroot=installroot, outroot=self.outputdir, + runtime=runtime, isolabel=isolabel, + domacboot=domacboot, doupgrade=doupgrade, + templatedir=self.templatedir, + add_templates=add_arch_templates, + add_template_vars=add_arch_template_vars, + workdir=self.workdir) + + logger.info("rebuilding initramfs images") + if not user_dracut_args: + dracut_args = DRACUT_DEFAULT + else: + dracut_args = [] + for arg in user_dracut_args: + dracut_args += arg.split(" ", 1) + + anaconda_args = dracut_args + ["--add", "anaconda pollcdrom qemu qemu-net"] + + # ppc64 cannot boot an initrd > 32MiB so remove some drivers + if self.arch.basearch in ("ppc64", "ppc64le"): + dracut_args.extend(["--omit-drivers", REMOVE_PPC64_DRIVERS]) + + # Only omit dracut modules from the initrd so that they're kept for + # upgrade.img + anaconda_args.extend(["--omit", REMOVE_PPC64_MODULES]) + + logger.info("dracut args = %s", dracut_args) + logger.info("anaconda args = %s", anaconda_args) + treebuilder.rebuild_initrds(add_args=anaconda_args) + + logger.info("populating output tree and building boot images") + treebuilder.build() + + # write .treeinfo file and we're done + treeinfo = TreeInfo(self.product.name, self.product.version, + self.product.variant, self.arch.basearch) + for section, data in treebuilder.treeinfo_data.items(): + treeinfo.add_section(section, data) + treeinfo.write(joinpaths(self.outputdir, ".treeinfo")) + + # cleanup + if remove_temp: + remove(self.workdir)
+ + +
[docs]def get_buildarch(dbo): + # get architecture of the available anaconda package + buildarch = None + q = dbo.sack.query() + a = q.available() + for anaconda in a.filter(name="anaconda-core"): + if anaconda.arch != "src": + buildarch = anaconda.arch + break + if not buildarch: + logger.critical("no anaconda-core package in the repository") + sys.exit(1) + + return buildarch
+ + +
[docs]def setup_logging(logfile, theLogger): + """ + Setup the various logs + + :param logfile: filename to write the log to + :type logfile: string + :param theLogger: top-level logger + :type theLogger: logging.Logger + """ + if not os.path.isdir(os.path.abspath(os.path.dirname(logfile))): + os.makedirs(os.path.abspath(os.path.dirname(logfile))) + + # Setup logging to console and to logfile + logger.setLevel(logging.DEBUG) + theLogger.setLevel(logging.DEBUG) + + sh = logging.StreamHandler() + sh.setLevel(logging.INFO) + fmt = logging.Formatter("%(asctime)s: %(message)s") + sh.setFormatter(fmt) + logger.addHandler(sh) + theLogger.addHandler(sh) + + fh = logging.FileHandler(filename=logfile, mode="w") + fh.setLevel(logging.DEBUG) + fmt = logging.Formatter("%(asctime)s %(levelname)s %(name)s: %(message)s") + fh.setFormatter(fmt) + logger.addHandler(fh) + theLogger.addHandler(fh) + + # External program output log + program_log.setLevel(logging.DEBUG) + f = os.path.abspath(os.path.dirname(logfile))+"/program.log" + fh = logging.FileHandler(filename=f, mode="w") + fh.setLevel(logging.DEBUG) + fmt = logging.Formatter("%(asctime)s %(levelname)s: %(message)s") + fh.setFormatter(fmt) + program_log.addHandler(fh)
+ + +
[docs]def find_templates(templatedir="/usr/share/lorax"): + """ Find the templates to use. + + :param str templatedir: Top directory to search for templates + :returns: Path to templates + :rtype: str + + If there is a templates.d directory under templatedir the + lowest numbered directory entry is returned. + + eg. /usr/share/lorax/templates.d/99-generic/ + """ + if os.path.isdir(joinpaths(templatedir, "templates.d")): + try: + templatedir = sorted(glob(joinpaths(templatedir, "templates.d", "*")))[0] + except IndexError: + pass + return templatedir
+ +
[docs]def log_selinux_state(): + """Log the current state of selinux""" + if selinux.is_selinux_enabled(): + if selinux.security_getenforce(): + logger.info("selinux is enabled and in Enforcing mode") + else: + logger.info("selinux is enabled and in Permissive mode") + else: + logger.info("selinux is Disabled")
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/bisect.html b/f29-branch/_modules/pylorax/api/bisect.html new file mode 100644 index 00000000..61e82b53 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/bisect.html @@ -0,0 +1,266 @@ + + + + + + + + + + + pylorax.api.bisect — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.bisect

+#
+# Copyright (C) 2018 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, see <http://www.gnu.org/licenses/>.
+#
+
[docs]def insort_left(a, x, key=None, lo=0, hi=None): + """Insert item x in list a, and keep it sorted assuming a is sorted. + + :param a: sorted list + :type a: list + :param x: item to insert into the list + :type x: object + :param key: Function to use to compare items in the list + :type key: function + :returns: index where the item was inserted + :rtype: int + + If x is already in a, insert it to the left of the leftmost x. + Optional args lo (default 0) and hi (default len(a)) bound the + slice of a to be searched. + + This is a modified version of bisect.insort_left that can use a + function for the compare, and returns the index position where it + was inserted. + """ + if key is None: + key = lambda i: i + + if lo < 0: + raise ValueError('lo must be non-negative') + if hi is None: + hi = len(a) + while lo < hi: + mid = (lo+hi)//2 + if key(a[mid]) < key(x): lo = mid+1 + else: hi = mid + a.insert(lo, x) + return lo
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/checkparams.html b/f29-branch/_modules/pylorax/api/checkparams.html new file mode 100644 index 00000000..dd17a986 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/checkparams.html @@ -0,0 +1,261 @@ + + + + + + + + + + + pylorax.api.checkparams — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.checkparams

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+
+import logging
+log = logging.getLogger("lorax-composer")
+
+from flask import jsonify
+from functools import update_wrapper
+
+# A decorator for checking the parameters provided to the API route implementing
+# functions.  The tuples parameter is a list of tuples.  Each tuple is the string
+# name of a parameter ("blueprint_name", not blueprint_name), the value it's set
+# to by flask if the caller did not provide it, and a message to be returned to
+# the user.
+#
+# If the parameter is set to its default, the error message is returned.  Otherwise,
+# the decorated function is called and its return value is returned.
+
[docs]def checkparams(tuples): + def decorator(f): + def wrapped_function(*args, **kwargs): + for tup in tuples: + if kwargs[tup[0]] == tup[1]: + log.error("(%s) %s", f.__name__, tup[2]) + return jsonify(status=False, errors=[tup[2]]), 400 + + return f(*args, **kwargs) + + return update_wrapper(wrapped_function, f) + + return decorator
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/cmdline.html b/f29-branch/_modules/pylorax/api/cmdline.html new file mode 100644 index 00000000..b33e9d79 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/cmdline.html @@ -0,0 +1,280 @@ + + + + + + + + + + + pylorax.api.cmdline — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.cmdline

+#
+# cmdline.py
+#
+# Copyright (C) 2018 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, see <http://www.gnu.org/licenses/>.
+#
+import os
+import sys
+import argparse
+
+from pylorax import vernum
+
+DEFAULT_USER  = "root"
+DEFAULT_GROUP = "weldr"
+
+version = "{0}-{1}".format(os.path.basename(sys.argv[0]), vernum)
+
+
[docs]def lorax_composer_parser(): + """ Return the ArgumentParser for lorax-composer""" + + parser = argparse.ArgumentParser(description="Lorax Composer API Server", + fromfile_prefix_chars="@") + + parser.add_argument("--socket", default="/run/weldr/api.socket", metavar="SOCKET", + help="Path to the socket file to listen on") + parser.add_argument("--user", default=DEFAULT_USER, metavar="USER", + help="User to use for reduced permissions") + parser.add_argument("--group", default=DEFAULT_GROUP, metavar="GROUP", + help="Group to set ownership of the socket to") + parser.add_argument("--log", dest="logfile", default="/var/log/lorax-composer/composer.log", metavar="LOG", + help="Path to logfile (/var/log/lorax-composer/composer.log)") + parser.add_argument("--mockfiles", default="/var/tmp/bdcs-mockfiles/", metavar="MOCKFILES", + help="Path to JSON files used for /api/mock/ paths (/var/tmp/bdcs-mockfiles/)") + parser.add_argument("--sharedir", type=os.path.abspath, metavar="SHAREDIR", + help="Directory containing all the templates. Overrides config file sharedir") + parser.add_argument("-V", action="store_true", dest="showver", + help="show program's version number and exit") + parser.add_argument("-c", "--config", default="/etc/lorax/composer.conf", metavar="CONFIG", + help="Path to lorax-composer configuration file.") + parser.add_argument("--releasever", default=None, metavar="STRING", + help="Release version to use for $releasever in dnf repository urls") + parser.add_argument("--tmp", default="/var/tmp", + help="Top level temporary directory") + parser.add_argument("--proxy", default=None, metavar="PROXY", + help="Set proxy for DNF, overrides configuration file setting.") + parser.add_argument("--no-system-repos", action="store_true", default=False, + help="Do not copy over system repos from /etc/yum.repos.d/ at startup") + parser.add_argument("BLUEPRINTS", metavar="BLUEPRINTS", + help="Path to the blueprints") + + return parser
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/compose.html b/f29-branch/_modules/pylorax/api/compose.html new file mode 100644 index 00000000..e4a60695 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/compose.html @@ -0,0 +1,1422 @@ + + + + + + + + + + + pylorax.api.compose — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.compose

+# Copyright (C) 2018-2019 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, see <http://www.gnu.org/licenses/>.
+#
+""" Setup for composing an image
+
+Adding New Output Types
+-----------------------
+
+The new output type must add a kickstart template to ./share/composer/ where the
+name of the kickstart (without the trailing .ks) matches the entry in compose_args.
+
+The kickstart should not have any url or repo entries, these will be added at build
+time. The %packages section should be the last thing, and while it can contain mandatory
+packages required by the output type, it should not have the trailing %end because the
+package NEVRAs will be appended to it at build time.
+
+compose_args should have a name matching the kickstart, and it should set the novirt_install
+parameters needed to generate the desired output. Other types should be set to False.
+
+"""
+import logging
+log = logging.getLogger("lorax-composer")
+
+import os
+from glob import glob
+from io import StringIO
+from math import ceil
+import pytoml as toml
+import shutil
+from uuid import uuid4
+
+# Use pykickstart to calculate disk image size
+from pykickstart.parser import KickstartParser
+from pykickstart.version import makeVersion
+
+from pylorax import ArchData, find_templates, get_buildarch
+from pylorax.api.gitrpm import create_gitrpm_repo
+from pylorax.api.projects import projects_depsolve, projects_depsolve_with_size, dep_nevra
+from pylorax.api.projects import ProjectsError
+from pylorax.api.recipes import read_recipe_and_id
+from pylorax.api.timestamp import TS_CREATED, write_timestamp
+from pylorax.base import DataHolder
+from pylorax.imgutils import default_image_name
+from pylorax.ltmpl import LiveTemplateRunner
+from pylorax.sysutils import joinpaths, flatconfig
+
+
+
[docs]def test_templates(dbo, share_dir): + """ Try depsolving each of the the templates and report any errors + + :param dbo: dnf base object + :type dbo: dnf.Base + :returns: List of template types and errors + :rtype: List of errors + + Return a list of templates and errors encountered or an empty list + """ + template_errors = [] + for compose_type in compose_types(share_dir): + # Read the kickstart template for this type + ks_template_path = joinpaths(share_dir, "composer", compose_type) + ".ks" + ks_template = open(ks_template_path, "r").read() + + # How much space will the packages in the default template take? + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(ks_template+"\n%end\n") + pkgs = [(name, "*") for name in ks.handler.packages.packageList] + grps = [grp.name for grp in ks.handler.packages.groupList] + try: + projects_depsolve(dbo, pkgs, grps) + except ProjectsError as e: + template_errors.append("Error depsolving %s: %s" % (compose_type, str(e))) + + return template_errors
+ + +
[docs]def repo_to_ks(r, url="url"): + """ Return a kickstart line with the correct args. + :param r: DNF repository information + :type r: dnf.Repo + :param url: "url" or "baseurl" to use for the baseurl parameter + :type url: str + :returns: kickstart command arguments for url/repo command + :rtype: str + + Set url to "baseurl" if it is a repo, leave it as "url" for the installation url. + """ + cmd = "" + # url uses --url not --baseurl + if r.baseurl: + cmd += '--%s="%s" ' % (url, r.baseurl[0]) + elif r.metalink: + cmd += '--metalink="%s" ' % r.metalink + elif r.mirrorlist: + cmd += '--mirrorlist="%s" ' % r.mirrorlist + else: + raise RuntimeError("Repo has no baseurl, metalink, or mirrorlist") + + if r.proxy: + cmd += '--proxy="%s" ' % r.proxy + + if not r.sslverify: + cmd += '--noverifyssl' + + if r.sslcacert: + cmd += ' --sslcacert="%s"' % r.sslcacert + if r.sslclientcert: + cmd += ' --sslclientcert="%s"' % r.sslclientcert + if r.sslclientkey: + cmd += ' --sslclientkey="%s"' % r.sslclientkey + + return cmd
+ + +
[docs]def bootloader_append(line, kernel_append): + """ Insert the kernel_append string into the --append argument + + :param line: The bootloader ... line + :type line: str + :param kernel_append: The arguments to append to the --append section + :type kernel_append: str + + Using pykickstart to process the line is the best way to make sure it + is parsed correctly, and re-assembled for inclusion into the final kickstart + """ + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(line) + + if ks.handler.bootloader.appendLine: + ks.handler.bootloader.appendLine += " %s" % kernel_append + else: + ks.handler.bootloader.appendLine = kernel_append + + # Converting back to a string includes a comment, return just the bootloader line + return str(ks.handler.bootloader).splitlines()[-1]
+ + +
[docs]def get_kernel_append(recipe): + """Return the customizations.kernel append value + + :param recipe: + :type recipe: Recipe object + :returns: append value or empty string + :rtype: str + """ + if "customizations" not in recipe or \ + "kernel" not in recipe["customizations"] or \ + "append" not in recipe["customizations"]["kernel"]: + return "" + return recipe["customizations"]["kernel"]["append"]
+ + +
[docs]def timezone_cmd(line, settings): + """ Update the timezone line with the settings + + :param line: The timezone ... line + :type line: str + :param settings: A dict with timezone and/or ntpservers list + :type settings: dict + + Using pykickstart to process the line is the best way to make sure it + is parsed correctly, and re-assembled for inclusion into the final kickstart + """ + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(line) + + if "timezone" in settings: + ks.handler.timezone.timezone = settings["timezone"] + if "ntpservers" in settings: + ks.handler.timezone.ntpservers = settings["ntpservers"] + + # Converting back to a string includes a comment, return just the timezone line + return str(ks.handler.timezone).splitlines()[-1]
+ + +
[docs]def get_timezone_settings(recipe): + """Return the customizations.timezone dict + + :param recipe: + :type recipe: Recipe object + :returns: append value or empty string + :rtype: dict + """ + if "customizations" not in recipe or \ + "timezone" not in recipe["customizations"]: + return {} + return recipe["customizations"]["timezone"]
+ + +
[docs]def lang_cmd(line, languages): + """ Update the lang line with the languages + + :param line: The lang ... line + :type line: str + :param settings: The list of languages + :type settings: list + + Using pykickstart to process the line is the best way to make sure it + is parsed correctly, and re-assembled for inclusion into the final kickstart + """ + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(line) + + if languages: + ks.handler.lang.lang = languages[0] + + if len(languages) > 1: + ks.handler.lang.addsupport = languages[1:] + + # Converting back to a string includes a comment, return just the lang line + return str(ks.handler.lang).splitlines()[-1]
+ + +
[docs]def get_languages(recipe): + """Return the customizations.locale.languages list + + :param recipe: The recipe + :type recipe: Recipe object + :returns: list of language strings + :rtype: list + """ + if "customizations" not in recipe or \ + "locale" not in recipe["customizations"] or \ + "languages" not in recipe["customizations"]["locale"]: + return [] + return recipe["customizations"]["locale"]["languages"]
+ + +
[docs]def keyboard_cmd(line, layout): + """ Update the keyboard line with the layout + + :param line: The keyboard ... line + :type line: str + :param settings: The keyboard layout + :type settings: str + + Using pykickstart to process the line is the best way to make sure it + is parsed correctly, and re-assembled for inclusion into the final kickstart + """ + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(line) + + if layout: + ks.handler.keyboard.keyboard = layout + ks.handler.keyboard.vc_keymap = "" + ks.handler.keyboard.x_layouts = [] + + # Converting back to a string includes a comment, return just the keyboard line + return str(ks.handler.keyboard).splitlines()[-1]
+ + +
[docs]def get_keyboard_layout(recipe): + """Return the customizations.locale.keyboard list + + :param recipe: The recipe + :type recipe: Recipe object + :returns: The keyboard layout string + :rtype: str + """ + if "customizations" not in recipe or \ + "locale" not in recipe["customizations"] or \ + "keyboard" not in recipe["customizations"]["locale"]: + return [] + return recipe["customizations"]["locale"]["keyboard"]
+ + +
[docs]def firewall_cmd(line, settings): + """ Update the firewall line with the new ports and services + + :param line: The firewall ... line + :type line: str + :param settings: A dict with the list of services and ports to enable and disable + :type settings: dict + + Using pykickstart to process the line is the best way to make sure it + is parsed correctly, and re-assembled for inclusion into the final kickstart + """ + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(line) + + # Do not override firewall --disabled + if ks.handler.firewall.enabled != False and settings: + ks.handler.firewall.ports = sorted(set(settings["ports"] + ks.handler.firewall.ports)) + ks.handler.firewall.services = sorted(set(settings["enabled"] + ks.handler.firewall.services)) + ks.handler.firewall.remove_services = sorted(set(settings["disabled"] + ks.handler.firewall.remove_services)) + + # Converting back to a string includes a comment, return just the keyboard line + return str(ks.handler.firewall).splitlines()[-1]
+ + +
[docs]def get_firewall_settings(recipe): + """Return the customizations.firewall settings + + :param recipe: The recipe + :type recipe: Recipe object + :returns: A dict of settings + :rtype: dict + """ + settings = {"ports": [], "enabled": [], "disabled": []} + + if "customizations" not in recipe or \ + "firewall" not in recipe["customizations"]: + return settings + + settings["ports"] = recipe["customizations"]["firewall"].get("ports", []) + + if "services" in recipe["customizations"]["firewall"]: + settings["enabled"] = recipe["customizations"]["firewall"]["services"].get("enabled", []) + settings["disabled"] = recipe["customizations"]["firewall"]["services"].get("disabled", []) + return settings
+ + +
[docs]def services_cmd(line, settings): + """ Update the services line with additional services to enable/disable + + :param line: The services ... line + :type line: str + :param settings: A dict with the list of services to enable and disable + :type settings: dict + + Using pykickstart to process the line is the best way to make sure it + is parsed correctly, and re-assembled for inclusion into the final kickstart + """ + # Empty services and no additional settings, return an empty string + if not line and not settings["enabled"] and not settings["disabled"]: + return "" + + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + + # Allow passing in a 'default' so that the enable/disable may be applied to it, without + # parsing it and emitting a kickstart error message + if line != "services": + ks.readKickstartFromString(line) + + # Add to any existing services, removing any duplicates + ks.handler.services.enabled = sorted(set(settings["enabled"] + ks.handler.services.enabled)) + ks.handler.services.disabled = sorted(set(settings["disabled"] + ks.handler.services.disabled)) + + # Converting back to a string includes a comment, return just the keyboard line + return str(ks.handler.services).splitlines()[-1]
+ + +
[docs]def get_services(recipe): + """Return the customizations.services settings + + :param recipe: The recipe + :type recipe: Recipe object + :returns: A dict of settings + :rtype: dict + """ + settings = {"enabled": [], "disabled": []} + + if "customizations" not in recipe or \ + "services" not in recipe["customizations"]: + return settings + + settings["enabled"] = sorted(recipe["customizations"]["services"].get("enabled", [])) + settings["disabled"] = sorted(recipe["customizations"]["services"].get("disabled", [])) + return settings
+ + +
[docs]def get_default_services(recipe): + """Get the default string for services, based on recipe + :param recipe: The recipe + + :type recipe: Recipe object + :returns: string with "services" or "" + :rtype: str + + When no services have been selected we don't need to add anything to the kickstart + so return an empty string. Otherwise return "services" which will be updated with + the settings. + """ + services = get_services(recipe) + + if services["enabled"] or services["disabled"]: + return "services" + else: + return ""
+ + +
[docs]def customize_ks_template(ks_template, recipe): + """ Customize the kickstart template and return it + + :param ks_template: The kickstart template + :type ks_template: str + :param recipe: + :type recipe: Recipe object + + Apply customizations to existing template commands, or add defaults for ones that are + missing and required. + + Apply customizations.kernel.append to the bootloader argument in the template. + Add bootloader line if it is missing. + + Add default timezone if needed. It does NOT replace an existing timezone entry + """ + # Commands to be modified [NEW-COMMAND-FUNC, NEW-VALUE, DEFAULT, REPLACE] + # The function is called with a kickstart command string and the value to replace + # The value is specific to the command, and is understood by the function + # The default is a complete kickstart command string, suitable for writing to the template + # If REPLACE is False it will not change an existing entry only add a missing one + commands = {"bootloader": [bootloader_append, + get_kernel_append(recipe), + 'bootloader --location=none', True], + "timezone": [timezone_cmd, + get_timezone_settings(recipe), + 'timezone UTC', False], + "lang": [lang_cmd, + get_languages(recipe), + 'lang en_US.UTF-8', True], + "keyboard": [keyboard_cmd, + get_keyboard_layout(recipe), + 'keyboard --xlayouts us --vckeymap us', True], + "firewall": [firewall_cmd, + get_firewall_settings(recipe), + 'firewall --enabled', True], + "services": [services_cmd, + get_services(recipe), + get_default_services(recipe), True] + } + found = {} + + output = StringIO() + for line in ks_template.splitlines(): + for cmd in commands: + (new_command, value, default, replace) = commands[cmd] + if line.startswith(cmd): + found[cmd] = True + if value and replace: + log.debug("Replacing %s with %s", cmd, value) + print(new_command(line, value), file=output) + else: + log.debug("Skipping %s", cmd) + print(line, file=output) + break + else: + # No matches, write the line as-is + print(line, file=output) + + # Write out defaults for the ones not found + # These must go FIRST because the template still needs to have the packages added + defaults = StringIO() + for cmd in commands: + if cmd in found: + continue + (new_command, value, default, _) = commands[cmd] + if value and default: + log.debug("Setting %s to use %s", cmd, value) + print(new_command(default, value), file=defaults) + elif default: + log.debug("Setting %s to %s", cmd, default) + print(default, file=defaults) + + return defaults.getvalue() + output.getvalue()
+ + +
[docs]def write_ks_root(f, user): + """ Write kickstart root password and sshkey entry + + :param f: kickstart file object + :type f: open file object + :param user: A blueprint user dictionary + :type user: dict + :returns: True if it wrote a rootpw command to the kickstart + :rtype: bool + + If the entry contains a ssh key, use sshkey to write it + If it contains password, use rootpw to set it + + root cannot be used with the user command. So only key and password are supported + for root. + """ + wrote_rootpw = False + + # ssh key uses the sshkey kickstart command + if "key" in user: + f.write('sshkey --user %s "%s"\n' % (user["name"], user["key"])) + + if "password" in user: + if any(user["password"].startswith(prefix) for prefix in ["$2b$", "$6$", "$5$"]): + log.debug("Detected pre-crypted password") + f.write('rootpw --iscrypted "%s"\n' % user["password"]) + wrote_rootpw = True + else: + log.debug("Detected plaintext password") + f.write('rootpw --plaintext "%s"\n' % user["password"]) + wrote_rootpw = True + + return wrote_rootpw
+ +
[docs]def write_ks_user(f, user): + """ Write kickstart user and sshkey entry + + :param f: kickstart file object + :type f: open file object + :param user: A blueprint user dictionary + :type user: dict + + If the entry contains a ssh key, use sshkey to write it + All of the user fields are optional, except name, write out a kickstart user entry + with whatever options are relevant. + """ + # ssh key uses the sshkey kickstart command + if "key" in user: + f.write('sshkey --user %s "%s"\n' % (user["name"], user["key"])) + + # Write out the user kickstart command, much of it is optional + f.write("user --name %s" % user["name"]) + if "home" in user: + f.write(" --homedir %s" % user["home"]) + + if "password" in user: + if any(user["password"].startswith(prefix) for prefix in ["$2b$", "$6$", "$5$"]): + log.debug("Detected pre-crypted password") + f.write(" --iscrypted") + else: + log.debug("Detected plaintext password") + f.write(" --plaintext") + + f.write(" --password \"%s\"" % user["password"]) + + if "shell" in user: + f.write(" --shell %s" % user["shell"]) + + if "uid" in user: + f.write(" --uid %d" % int(user["uid"])) + + if "gid" in user: + f.write(" --gid %d" % int(user["gid"])) + + if "description" in user: + f.write(" --gecos \"%s\"" % user["description"]) + + if "groups" in user: + f.write(" --groups %s" % ",".join(user["groups"])) + + f.write("\n")
+ + +
[docs]def write_ks_group(f, group): + """ Write kickstart group entry + + :param f: kickstart file object + :type f: open file object + :param group: A blueprint group dictionary + :type user: dict + + gid is optional + """ + if "name" not in group: + raise RuntimeError("group entry requires a name") + + f.write("group --name %s" % group["name"]) + if "gid" in group: + f.write(" --gid %d" % int(group["gid"])) + + f.write("\n")
+ + +
[docs]def add_customizations(f, recipe): + """ Add customizations to the kickstart file + + :param f: kickstart file object + :type f: open file object + :param recipe: + :type recipe: Recipe object + :returns: None + :raises: RuntimeError if there was a problem writing to the kickstart + """ + if "customizations" not in recipe: + f.write('rootpw --lock\n') + return + customizations = recipe["customizations"] + + # allow customizations to be incorrectly specified as [[customizations]] instead of [customizations] + if isinstance(customizations, list): + customizations = customizations[0] + + if "hostname" in customizations: + f.write("network --hostname=%s\n" % customizations["hostname"]) + + # TODO - remove this, should use user section to define this + if "sshkey" in customizations: + # This is a list of entries + for sshkey in customizations["sshkey"]: + if "user" not in sshkey or "key" not in sshkey: + log.error("%s is incorrect, skipping", sshkey) + continue + f.write('sshkey --user %s "%s"\n' % (sshkey["user"], sshkey["key"])) + + # Creating a user also creates a group. Make a list of the names for later + user_groups = [] + # kickstart requires a rootpw line + wrote_rootpw = False + if "user" in customizations: + # only name is required, everything else is optional + for user in customizations["user"]: + if "name" not in user: + raise RuntimeError("user entry requires a name") + + # root is special, cannot use normal user command for it + if user["name"] == "root": + wrote_rootpw = write_ks_root(f, user) + continue + + write_ks_user(f, user) + user_groups.append(user["name"]) + + if "group" in customizations: + for group in customizations["group"]: + if group["name"] not in user_groups: + write_ks_group(f, group) + else: + log.warning("Skipping group %s, already created by user", group["name"]) + + # Lock the root account if no root user password has been specified + if not wrote_rootpw: + f.write('rootpw --lock\n')
+ + +
[docs]def get_extra_pkgs(dbo, share_dir, compose_type): + """Return extra packages needed for the output type + + :param dbo: dnf base object + :type dbo: dnf.Base + :param share_dir: Path to the top level share directory + :type share_dir: str + :param compose_type: The type of output to create from the recipe + :type compose_type: str + :returns: List of package names (name only, not NEVRA) + :rtype: list + + Currently this is only needed by live-iso, it reads ./live/live-install.tmpl and + processes only the installpkg lines. It lists the packages needed to complete creation of the + iso using the templates such as x86.tmpl + + Keep in mind that the live-install.tmpl is shared between livemedia-creator and lorax-composer, + even though the results are applied differently. + """ + if compose_type != "live-iso": + return [] + + # get the arch information to pass to the runner + arch = ArchData(get_buildarch(dbo)) + defaults = DataHolder(basearch=arch.basearch) + templatedir = joinpaths(find_templates(share_dir), "live") + runner = LiveTemplateRunner(dbo, templatedir=templatedir, defaults=defaults) + runner.run("live-install.tmpl") + log.debug("extra pkgs = %s", runner.pkgs) + + return runner.pkgnames
+ + +
[docs]def start_build(cfg, dnflock, gitlock, branch, recipe_name, compose_type, test_mode=0): + """ Start the build + + :param cfg: Configuration object + :type cfg: ComposerConfig + :param dnflock: Lock and YumBase for depsolving + :type dnflock: YumLock + :param recipe: The recipe to build + :type recipe: str + :param compose_type: The type of output to create from the recipe + :type compose_type: str + :returns: Unique ID for the build that can be used to track its status + :rtype: str + """ + share_dir = cfg.get("composer", "share_dir") + lib_dir = cfg.get("composer", "lib_dir") + + # Make sure compose_type is valid + if compose_type not in compose_types(share_dir): + raise RuntimeError("Invalid compose type (%s), must be one of %s" % (compose_type, compose_types(share_dir))) + + # Some image types (live-iso) need extra packages for composer to execute the output template + with dnflock.lock: + extra_pkgs = get_extra_pkgs(dnflock.dbo, share_dir, compose_type) + log.debug("Extra packages needed for %s: %s", compose_type, extra_pkgs) + + with gitlock.lock: + (commit_id, recipe) = read_recipe_and_id(gitlock.repo, branch, recipe_name) + + # Combine modules and packages and depsolve the list + module_nver = recipe.module_nver + package_nver = recipe.package_nver + package_nver.extend([(name, '*') for name in extra_pkgs]) + + projects = sorted(set(module_nver+package_nver), key=lambda p: p[0].lower()) + deps = [] + log.info("depsolving %s", recipe["name"]) + try: + # This can possibly update repodata and reset the YumBase object. + with dnflock.lock_check: + (installed_size, deps) = projects_depsolve_with_size(dnflock.dbo, projects, recipe.group_names, with_core=False) + except ProjectsError as e: + log.error("start_build depsolve: %s", str(e)) + raise RuntimeError("Problem depsolving %s: %s" % (recipe["name"], str(e))) + + # Read the kickstart template for this type + ks_template_path = joinpaths(share_dir, "composer", compose_type) + ".ks" + ks_template = open(ks_template_path, "r").read() + + # How much space will the packages in the default template take? + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstartFromString(ks_template+"\n%end\n") + pkgs = [(name, "*") for name in ks.handler.packages.packageList] + grps = [grp.name for grp in ks.handler.packages.groupList] + try: + with dnflock.lock: + (template_size, _) = projects_depsolve_with_size(dnflock.dbo, pkgs, grps, with_core=not ks.handler.packages.nocore) + except ProjectsError as e: + log.error("start_build depsolve: %s", str(e)) + raise RuntimeError("Problem depsolving %s: %s" % (recipe["name"], str(e))) + log.debug("installed_size = %d, template_size=%d", installed_size, template_size) + + # Minimum LMC disk size is 1GiB, and anaconda bumps the estimated size up by 10% (which doesn't always work). + installed_size = int((installed_size+template_size)) * 1.2 + log.debug("/ partition size = %d", installed_size) + + # Create the results directory + build_id = str(uuid4()) + results_dir = joinpaths(lib_dir, "results", build_id) + os.makedirs(results_dir) + + # Write the recipe commit hash + commit_path = joinpaths(results_dir, "COMMIT") + with open(commit_path, "w") as f: + f.write(commit_id) + + # Write the original recipe + recipe_path = joinpaths(results_dir, "blueprint.toml") + with open(recipe_path, "w") as f: + f.write(recipe.toml()) + + # Write the frozen recipe + frozen_recipe = recipe.freeze(deps) + recipe_path = joinpaths(results_dir, "frozen.toml") + with open(recipe_path, "w") as f: + f.write(frozen_recipe.toml()) + + # Write out the dependencies to the results dir + deps_path = joinpaths(results_dir, "deps.toml") + with open(deps_path, "w") as f: + f.write(toml.dumps({"packages":deps})) + + # Save a copy of the original kickstart + shutil.copy(ks_template_path, results_dir) + + with dnflock.lock: + repos = list(dnflock.dbo.repos.iter_enabled()) + if not repos: + raise RuntimeError("No enabled repos, canceling build.") + + # Create the git rpms, if any, and return the path to the repo under results_dir + gitrpm_repo = create_gitrpm_repo(results_dir, recipe) + + # Create the final kickstart with repos and package list + ks_path = joinpaths(results_dir, "final-kickstart.ks") + with open(ks_path, "w") as f: + ks_url = repo_to_ks(repos[0], "url") + log.debug("url = %s", ks_url) + f.write('url %s\n' % ks_url) + for idx, r in enumerate(repos[1:]): + ks_repo = repo_to_ks(r, "baseurl") + log.debug("repo composer-%s = %s", idx, ks_repo) + f.write('repo --name="composer-%s" %s\n' % (idx, ks_repo)) + + if gitrpm_repo: + log.debug("repo gitrpms = %s", gitrpm_repo) + f.write('repo --name="gitrpms" --baseurl="file://%s"\n' % gitrpm_repo) + + # Setup the disk for booting + # TODO Add GPT and UEFI boot support + f.write('clearpart --all --initlabel\n') + + # Write the root partition and it's size in MB (rounded up) + f.write('part / --size=%d\n' % ceil(installed_size / 1024**2)) + + # Some customizations modify the template before writing it + f.write(customize_ks_template(ks_template, recipe)) + + for d in deps: + f.write(dep_nevra(d)+"\n") + + # Include the rpms from the gitrpm repo directory + if gitrpm_repo: + for rpm in glob(os.path.join(gitrpm_repo, "*.rpm")): + f.write(os.path.basename(rpm)[:-4]+"\n") + + f.write("%end\n") + + # Other customizations can be appended to the kickstart + add_customizations(f, recipe) + + # Setup the config to pass to novirt_install + log_dir = joinpaths(results_dir, "logs/") + cfg_args = compose_args(compose_type) + + # Get the title, project, and release version from the host + if not os.path.exists("/etc/os-release"): + log.error("/etc/os-release is missing, cannot determine product or release version") + os_release = flatconfig("/etc/os-release") + + log.debug("os_release = %s", dict(os_release.items())) + + cfg_args["title"] = os_release.get("PRETTY_NAME", "") + cfg_args["project"] = os_release.get("NAME", "") + cfg_args["releasever"] = os_release.get("VERSION_ID", "") + cfg_args["volid"] = "" + cfg_args["extra_boot_args"] = get_kernel_append(recipe) + + if "compression" not in cfg_args: + cfg_args["compression"] = "xz" + + if "compress_args" not in cfg_args: + cfg_args["compress_args"] = [] + + cfg_args.update({ + "ks": [ks_path], + "logfile": log_dir, + "timeout": 60, # 60 minute timeout + }) + with open(joinpaths(results_dir, "config.toml"), "w") as f: + f.write(toml.dumps(cfg_args)) + + # Set the initial status + open(joinpaths(results_dir, "STATUS"), "w").write("WAITING") + + # Set the test mode, if requested + if test_mode > 0: + open(joinpaths(results_dir, "TEST"), "w").write("%s" % test_mode) + + write_timestamp(results_dir, TS_CREATED) + log.info("Adding %s (%s %s) to compose queue", build_id, recipe["name"], compose_type) + os.symlink(results_dir, joinpaths(lib_dir, "queue/new/", build_id)) + + return build_id
+ +# Supported output types +
[docs]def compose_types(share_dir): + r""" Returns a list of the supported output types + + The output types come from the kickstart names in /usr/share/lorax/composer/\*ks + """ + return sorted([os.path.basename(ks)[:-3] for ks in glob(joinpaths(share_dir, "composer/*.ks"))])
+ +
[docs]def compose_args(compose_type): + """ Returns the settings to pass to novirt_install for the compose type + + :param compose_type: The type of compose to create, from `compose_types()` + :type compose_type: str + + This will return a dict of options that match the ArgumentParser options for livemedia-creator. + These are the ones the define the type of output, it's filename, etc. + Other options will be filled in by `make_compose()` + """ + _MAP = {"tar": {"make_iso": False, + "make_disk": False, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": True, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": False, # False instead of None because of TOML + "qemu_args": [], + "image_name": default_image_name("xz", "root.tar"), + "tar_disk_name": None, + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "live-iso": {"make_iso": True, + "make_disk": False, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": False, # False instead of None because of TOML + "qemu_args": [], + "image_name": "live.iso", + "tar_disk_name": None, + "fs_label": "Anaconda", # Live booting may expect this to be 'Anaconda' + "image_only": False, + "app_name": None, + "app_template": None, + "app_file": None, + "iso_only": True, + "iso_name": "live.iso", + }, + "partitioned-disk": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": False, # False instead of None because of TOML + "qemu_args": [], + "image_name": "disk.img", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "qcow2": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": "qcow2", + "qemu_args": [], + "image_name": "disk.qcow2", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "ext4-filesystem": {"make_iso": False, + "make_disk": False, + "make_fsimage": True, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": False, # False instead of None because of TOML + "qemu_args": [], + "image_name": "filesystem.img", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "ami": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": False, + "qemu_args": [], + "image_name": "disk.ami", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "vhd": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": "vpc", + "qemu_args": ["-o", "subformat=fixed,force_size"], + "image_name": "disk.vhd", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "vmdk": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": "vmdk", + "qemu_args": [], + "image_name": "disk.vmdk", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "openstack": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": "qcow2", + "qemu_args": [], + "image_name": "disk.qcow2", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "google": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": True, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 1024, + "image_type": False, # False instead of None because of TOML + "qemu_args": [], + "image_name": "disk.tar.gz", + "tar_disk_name": "disk.raw", + "compression": "gzip", + "compress_args": ["-9"], + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "hyper-v": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": "vhdx", + "qemu_args": [], + "image_name": "disk.vhdx", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + "alibaba": {"make_iso": False, + "make_disk": True, + "make_fsimage": False, + "make_appliance": False, + "make_ami": False, + "make_tar": False, + "make_tar_disk": False, + "make_pxe_live": False, + "make_ostree_live": False, + "make_oci": False, + "make_vagrant": False, + "ostree": False, + "live_rootfs_keep_size": False, + "live_rootfs_size": 0, + "image_size_align": 0, + "image_type": "qcow2", + "qemu_args": [], + "image_name": "disk.qcow2", + "tar_disk_name": None, + "fs_label": "", + "image_only": True, + "app_name": None, + "app_template": None, + "app_file": None, + }, + } + return _MAP[compose_type]
+ +
[docs]def move_compose_results(cfg, results_dir): + """Move the final image to the results_dir and cleanup the unneeded compose files + + :param cfg: Build configuration + :type cfg: DataHolder + :param results_dir: Directory to put the results into + :type results_dir: str + """ + if cfg["make_tar"]: + shutil.move(joinpaths(cfg["result_dir"], cfg["image_name"]), results_dir) + elif cfg["make_iso"]: + # Output from live iso is always a boot.iso under images/, move and rename it + shutil.move(joinpaths(cfg["result_dir"], cfg["iso_name"]), joinpaths(results_dir, cfg["image_name"])) + elif cfg["make_disk"] or cfg["make_fsimage"]: + shutil.move(joinpaths(cfg["result_dir"], cfg["image_name"]), joinpaths(results_dir, cfg["image_name"])) + + + # Cleanup the compose directory, but only if it looks like a compose directory + if os.path.basename(cfg["result_dir"]) == "compose": + shutil.rmtree(cfg["result_dir"]) + else: + log.error("Incorrect compose directory, not cleaning up")
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/config.html b/f29-branch/_modules/pylorax/api/config.html new file mode 100644 index 00000000..eaf74472 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/config.html @@ -0,0 +1,355 @@ + + + + + + + + + + + pylorax.api.config — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.config

+#
+# Copyright (C) 2017  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, see <http://www.gnu.org/licenses/>.
+#
+import configparser
+import grp
+import os
+import pwd
+
+from pylorax.sysutils import joinpaths
+
+
[docs]class ComposerConfig(configparser.ConfigParser): +
[docs] def get_default(self, section, option, default): + try: + return self.get(section, option) + except configparser.Error: + return default
+ + +
[docs]def configure(conf_file="/etc/lorax/composer.conf", root_dir="/", test_config=False): + """lorax-composer configuration + + :param conf_file: Path to the config file overriding the default settings + :type conf_file: str + :param root_dir: Directory to prepend to paths, defaults to / + :type root_dir: str + :param test_config: Set to True to skip reading conf_file + :type test_config: bool + """ + conf = ComposerConfig() + + # set defaults + conf.add_section("composer") + conf.set("composer", "share_dir", os.path.realpath(joinpaths(root_dir, "/usr/share/lorax/"))) + conf.set("composer", "lib_dir", os.path.realpath(joinpaths(root_dir, "/var/lib/lorax/composer/"))) + conf.set("composer", "repo_dir", os.path.realpath(joinpaths(root_dir, "/var/lib/lorax/composer/repos.d/"))) + conf.set("composer", "dnf_conf", os.path.realpath(joinpaths(root_dir, "/var/tmp/composer/dnf.conf"))) + conf.set("composer", "dnf_root", os.path.realpath(joinpaths(root_dir, "/var/tmp/composer/dnf/root/"))) + conf.set("composer", "cache_dir", os.path.realpath(joinpaths(root_dir, "/var/tmp/composer/cache/"))) + conf.set("composer", "tmp", os.path.realpath(joinpaths(root_dir, "/var/tmp/"))) + + conf.add_section("users") + conf.set("users", "root", "1") + + # Enable all available repo files by default + conf.add_section("repos") + conf.set("repos", "use_system_repos", "1") + conf.set("repos", "enabled", "*") + + conf.add_section("dnf") + + if not test_config: + # read the config file + if os.path.isfile(conf_file): + conf.read(conf_file) + + return conf
+ +
[docs]def make_owned_dir(p_dir, uid, gid): + """Make a directory and its parents, setting owner and group + + :param p_dir: path to directory to create + :type p_dir: string + :param uid: uid of owner + :type uid: int + :param gid: gid of owner + :type gid: int + :returns: list of errors + :rtype: list of str + + Check to make sure it does not have o+rw permissions and that it is owned by uid:gid + """ + errors = [] + if not os.path.isdir(p_dir): + # Make sure no o+rw permissions are set + orig_umask = os.umask(0o006) + os.makedirs(p_dir, 0o771) + os.chown(p_dir, uid, gid) + os.umask(orig_umask) + else: + p_stat = os.stat(p_dir) + if p_stat.st_mode & 0o006 != 0: + errors.append("Incorrect permissions on %s, no o+rw permissions are allowed." % p_dir) + + if p_stat.st_gid != gid or p_stat.st_uid != 0: + gr_name = grp.getgrgid(gid).gr_name + u_name = pwd.getpwuid(uid) + errors.append("%s should be owned by %s:%s" % (p_dir, u_name, gr_name)) + + return errors
+ +
[docs]def make_dnf_dirs(conf, uid, gid): + """Make any missing dnf directories owned by user:group + + :param conf: The configuration to use + :type conf: ComposerConfig + :param uid: uid of owner + :type uid: int + :param gid: gid of owner + :type gid: int + :returns: list of errors + :rtype: list of str + """ + errors = [] + for p in ["dnf_conf", "repo_dir", "cache_dir", "dnf_root"]: + p_dir = os.path.abspath(conf.get("composer", p)) + if p == "dnf_conf": + p_dir = os.path.dirname(p_dir) + errors.extend(make_owned_dir(p_dir, uid, gid))
+ +
[docs]def make_queue_dirs(conf, gid): + """Make any missing queue directories + + :param conf: The configuration to use + :type conf: ComposerConfig + :param gid: Group ID that has access to the queue directories + :type gid: int + :returns: list of errors + :rtype: list of str + """ + errors = [] + lib_dir = conf.get("composer", "lib_dir") + for p in ["queue/run", "queue/new", "results"]: + p_dir = joinpaths(lib_dir, p) + errors.extend(make_owned_dir(p_dir, 0, gid)) + return errors
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/crossdomain.html b/f29-branch/_modules/pylorax/api/crossdomain.html new file mode 100644 index 00000000..a90449bb --- /dev/null +++ b/f29-branch/_modules/pylorax/api/crossdomain.html @@ -0,0 +1,281 @@ + + + + + + + + + + + pylorax.api.crossdomain — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.crossdomain

+#
+# Copyright (C) 2017  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, see <http://www.gnu.org/licenses/>.
+#
+
+# crossdomain decorator from - http://flask.pocoo.org/snippets/56/
+from datetime import timedelta
+from flask import make_response, request, current_app
+from functools import update_wrapper
+
+
+
[docs]def crossdomain(origin, methods=None, headers=None, + max_age=21600, attach_to_all=True, + automatic_options=True): + if methods is not None: + methods = ', '.join(sorted(x.upper() for x in methods)) + if headers is not None and not isinstance(headers, str): + headers = ', '.join(x.upper() for x in headers) + if not isinstance(origin, list): + origin = [origin] + if isinstance(max_age, timedelta): + max_age = int(max_age.total_seconds()) + + def get_methods(): + if methods is not None: + return methods + + options_resp = current_app.make_default_options_response() + return options_resp.headers['allow'] + + def decorator(f): + def wrapped_function(*args, **kwargs): + if automatic_options and request.method == 'OPTIONS': + resp = current_app.make_default_options_response() + else: + resp = make_response(f(*args, **kwargs)) + if not attach_to_all and request.method != 'OPTIONS': + return resp + + h = resp.headers + + h.extend([("Access-Control-Allow-Origin", orig) for orig in origin]) + h['Access-Control-Allow-Methods'] = get_methods() + h['Access-Control-Max-Age'] = str(max_age) + if headers is not None: + h['Access-Control-Allow-Headers'] = headers + return resp + + f.provide_automatic_options = False + f.required_methods = ['OPTIONS'] + return update_wrapper(wrapped_function, f) + return decorator
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/dnfbase.html b/f29-branch/_modules/pylorax/api/dnfbase.html new file mode 100644 index 00000000..496ec12b --- /dev/null +++ b/f29-branch/_modules/pylorax/api/dnfbase.html @@ -0,0 +1,398 @@ + + + + + + + + + + + pylorax.api.dnfbase — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.dnfbase

+#
+# Copyright (C) 2017-2018 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, see <http://www.gnu.org/licenses/>.
+#
+# pylint: disable=bad-preconf-access
+
+import logging
+log = logging.getLogger("lorax-composer")
+
+import dnf
+import dnf.logging
+from glob import glob
+import os
+import shutil
+from threading import Lock
+import time
+
+from pylorax import DEFAULT_PLATFORM_ID
+from pylorax.sysutils import flatconfig
+
+
[docs]class DNFLock(object): + """Hold the dnf.Base object and a Lock to control access to it. + + self.dbo is a property that returns the dnf.Base object, but it *may* change + from one call to the next if the upstream repositories have changed. + """ + def __init__(self, conf, expire_secs=6*60*60): + self._conf = conf + self._lock = Lock() + self.dbo = get_base_object(self._conf) + self._expire_secs = expire_secs + self._expire_time = time.time() + self._expire_secs + + @property + def lock(self): + """Check for repo updates (using expiration time) and return the lock + + If the repository has been updated, tear down the old dnf.Base and + create a new one. This is the only way to force dnf to use the new + metadata. + """ + if time.time() > self._expire_time: + return self.lock_check + return self._lock + + @property + def lock_check(self): + """Force a check for repo updates and return the lock + + Use this method sparingly, it removes the repodata and downloads a new copy every time. + """ + self._expire_time = time.time() + self._expire_secs + self.dbo.update_cache() + return self._lock
+ +
[docs]def get_base_object(conf): + """Get the DNF object with settings from the config file + + :param conf: configuration object + :type conf: ComposerParser + :returns: A DNF Base object + :rtype: dnf.Base + """ + cachedir = os.path.abspath(conf.get("composer", "cache_dir")) + dnfconf = os.path.abspath(conf.get("composer", "dnf_conf")) + dnfroot = os.path.abspath(conf.get("composer", "dnf_root")) + repodir = os.path.abspath(conf.get("composer", "repo_dir")) + + # Setup the config for the DNF Base object + dbo = dnf.Base() + dbc = dbo.conf +# TODO - Handle this +# dbc.logdir = logdir + dbc.installroot = dnfroot + if not os.path.isdir(dnfroot): + os.makedirs(dnfroot) + if not os.path.isdir(repodir): + os.makedirs(repodir) + + dbc.cachedir = cachedir + dbc.reposdir = [repodir] + dbc.install_weak_deps = False + dbc.prepend_installroot('persistdir') + # this is a weird 'AppendOption' thing that, when you set it, + # actually appends. Doing this adds 'nodocs' to the existing list + # of values, over in libdnf, it does not replace the existing values. + dbc.tsflags = ['nodocs'] + + if conf.get_default("dnf", "proxy", None): + dbc.proxy = conf.get("dnf", "proxy") + + if conf.has_option("dnf", "sslverify") and not conf.getboolean("dnf", "sslverify"): + dbc.sslverify = False + + _releasever = conf.get_default("composer", "releasever", None) + if not _releasever: + # Use the releasever of the host system + _releasever = dnf.rpm.detect_releasever("/") + log.info("releasever = %s", _releasever) + dbc.releasever = _releasever + + # DNF 3.2 needs to have module_platform_id set, otherwise depsolve won't work correctly + if not os.path.exists("/etc/os-release"): + log.warning("/etc/os-release is missing, cannot determine platform id, falling back to %s", DEFAULT_PLATFORM_ID) + platform_id = DEFAULT_PLATFORM_ID + else: + os_release = flatconfig("/etc/os-release") + platform_id = os_release.get("PLATFORM_ID", DEFAULT_PLATFORM_ID) + log.info("Using %s for module_platform_id", platform_id) + dbc.module_platform_id = platform_id + + # Make sure metadata is always current + dbc.metadata_expire = 0 + dbc.metadata_expire_filter = "never" + + # write the dnf configuration file + with open(dnfconf, "w") as f: + f.write(dbc.dump()) + + # dnf needs the repos all in one directory, composer uses repodir for this + # if system repos are supposed to be used, copy them into repodir, overwriting any previous copies + if not conf.has_option("repos", "use_system_repos") or conf.getboolean("repos", "use_system_repos"): + for repo_file in glob("/etc/yum.repos.d/*.repo"): + shutil.copy2(repo_file, repodir) + dbo.read_all_repos() + + # Remove any duplicate repo entries. These can cause problems with Anaconda, which will fail + # with space problems. + repos = sorted(list(r.id for r in dbo.repos.iter_enabled())) + seen = {"baseurl": [], "mirrorlist": [], "metalink": []} + for source_name in repos: + remove = False + repo = dbo.repos.get(source_name, None) + if repo is None: + log.warning("repo %s vanished while removing duplicates", source_name) + continue + if repo.baseurl: + if repo.baseurl[0] in seen["baseurl"]: + log.info("Removing duplicate repo: %s baseurl=%s", source_name, repo.baseurl[0]) + remove = True + else: + seen["baseurl"].append(repo.baseurl[0]) + elif repo.mirrorlist: + if repo.mirrorlist in seen["mirrorlist"]: + log.info("Removing duplicate repo: %s mirrorlist=%s", source_name, repo.mirrorlist) + remove = True + else: + seen["mirrorlist"].append(repo.mirrorlist) + elif repo.metalink: + if repo.metalink in seen["metalink"]: + log.info("Removing duplicate repo: %s metalink=%s", source_name, repo.metalink) + remove = True + else: + seen["metalink"].append(repo.metalink) + + if remove: + del dbo.repos[source_name] + + # Update the metadata from the enabled repos to speed up later operations + log.info("Updating repository metadata") + try: + dbo.fill_sack(load_system_repo=False) + dbo.read_comps() + dbo.update_cache() + except dnf.exceptions.Error as e: + log.error("Failed to update metadata: %s", str(e)) + raise RuntimeError("Fetching metadata failed: %s" % str(e)) + + return dbo
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/gitrpm.html b/f29-branch/_modules/pylorax/api/gitrpm.html new file mode 100644 index 00000000..d2d7413b --- /dev/null +++ b/f29-branch/_modules/pylorax/api/gitrpm.html @@ -0,0 +1,438 @@ + + + + + + + + + + + pylorax.api.gitrpm — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.gitrpm

+# Copyright (C) 2019 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, see <http://www.gnu.org/licenses/>.
+#
+""" Clone a git repository and package it as an rpm
+
+This module contains functions for cloning a git repo, creating a tar archive of
+the selected commit, branch, or tag, and packaging the files into an rpm that will
+be installed by anaconda when creating the image.
+"""
+import logging
+log = logging.getLogger("lorax-composer")
+
+import os
+from rpmfluff import SimpleRpmBuild
+import shutil
+import subprocess
+import tempfile
+import time
+
+from pylorax.sysutils import joinpaths
+
+
[docs]def get_repo_description(gitRepo): + """ Return a description including the git repo and reference + + :param gitRepo: A dict with the repository details + :type gitRepo: dict + :returns: A string with the git repo url and reference + :rtype: str + """ + return "Created from %s, reference '%s', on %s" % (gitRepo["repo"], gitRepo["ref"], time.ctime())
+ +
[docs]class GitArchiveTarball: + """Create a git archive of the selected git repo and reference""" + def __init__(self, gitRepo): + self._gitRepo = gitRepo + self.sourceName = self._gitRepo["rpmname"]+".tar.xz" + +
[docs] def write_file(self, sourcesDir): + """ Create the tar archive + + :param sourcesDir: Path to use for creating the archive + :type sourcesDir: str + + This clones the git repository and creates a git archive from the specified reference. + The result is in RPMNAME.tar.xz under the sourcesDir + """ + # Clone the repository into a temporary location + cmd = ["git", "clone", self._gitRepo["repo"], joinpaths(sourcesDir, "gitrepo")] + log.debug(cmd) + try: + subprocess.check_output(cmd) + except subprocess.CalledProcessError as e: + log.error("Failed to clone %s: %s", self._gitRepo["repo"], e.output) + raise RuntimeError("Failed to clone %s" % self._gitRepo["repo"]) + + oldcwd = os.getcwd() + try: + os.chdir(joinpaths(sourcesDir, "gitrepo")) + + # Configure archive to create a .tar.xz + cmd = ["git", "config", "tar.tar.xz.command", "xz -c"] + log.debug(cmd) + subprocess.check_call(cmd) + + cmd = ["git", "archive", "--prefix", self._gitRepo["rpmname"] + "/", "-o", joinpaths(sourcesDir, self.sourceName), self._gitRepo["ref"]] + log.debug(cmd) + try: + subprocess.check_output(cmd) + except subprocess.CalledProcessError as e: + log.error("Failed to archive %s: %s", self._gitRepo["repo"], e.output) + raise RuntimeError("Failed to clone %s" % self._gitRepo["repo"]) + finally: + # Cleanup even if there was an error + os.chdir(oldcwd) + shutil.rmtree(joinpaths(sourcesDir, "gitrepo"))
+ +
[docs]class GitRpmBuild(SimpleRpmBuild): + """Build an rpm containing files from a git repository""" + def __init__(self, *args, **kwargs): + self._base_dir = None + super().__init__(*args, **kwargs) + +
[docs] def check(self): + raise NotImplementedError
+ +
[docs] def get_base_dir(self): + """Place all the files under a temporary directory + rpmbuild/ + """ + if not self._base_dir: + self._base_dir = tempfile.mkdtemp(prefix="lorax-git-rpm.") + return joinpaths(self._base_dir, "rpmbuild")
+ +
[docs] def cleanup_tmpdir(self): + """Remove the temporary directory and all of its contents + """ + if len(self._base_dir) < 5: + raise RuntimeError("Invalid base_dir: %s" % self.get_base_dir()) + + shutil.rmtree(self._base_dir)
+ +
[docs] def clean(self): + """Remove the base directory from inside the tmpdir""" + if len(self.get_base_dir()) < 5: + raise RuntimeError("Invalid base_dir: %s" % self.get_base_dir()) + shutil.rmtree(self.get_base_dir(), ignore_errors=True)
+ +
[docs] def add_git_tarball(self, gitRepo): + """Add a tar archive of a git repository to the rpm + + :param gitRepo: A dict with the repository details + :type gitRepo: dict + + This populates the rpm with the URL of the git repository, the summary + describing the repo, the description of the repository and reference used, + and sets up the rpm to install the archive contents into the destination + path. + """ + self.addUrl(gitRepo["repo"]) + self.add_summary(gitRepo["summary"]) + self.add_description(get_repo_description(gitRepo)) + self.addLicense("Unknown") + sourceIndex = self.add_source(GitArchiveTarball(gitRepo)) + self.section_build += "tar -xvf %s\n" % self.sources[sourceIndex].sourceName + dest = os.path.normpath(gitRepo["destination"]) + # Prevent double slash root + if dest == "/": + dest = "" + self.create_parent_dirs(dest) + self.section_install += "cp -r %s/. $RPM_BUILD_ROOT/%s\n" % (gitRepo["rpmname"], dest) + sub = self.get_subpackage(None) + if not dest: + # / is special, we don't want to include / itself, just what's under it + sub.section_files += "/*\n" + else: + sub.section_files += "%s/\n" % dest
+ +
[docs]def make_git_rpm(gitRepo, dest): + """ Create an rpm from the specified git repo + + :param gitRepo: A dict with the repository details + :type gitRepo: dict + + This will clone the git repository, create an archive of the selected reference, + and build an rpm that will install the files from the repository under the destination + directory. The gitRepo dict should have the following fields:: + + rpmname: "server-config" + rpmversion: "1.0" + rpmrelease: "1" + summary: "Setup files for server deployment" + repo: "PATH OF GIT REPO TO CLONE" + ref: "v1.0" + destination: "/opt/server/" + + * rpmname: Name of the rpm to create, also used as the prefix name in the tar archive + * rpmversion: Version of the rpm, eg. "1.0.0" + * rpmrelease: Release of the rpm, eg. "1" + * summary: Summary string for the rpm + * repo: URL of the get repo to clone and create the archive from + * ref: Git reference to check out. eg. origin/branch-name, git tag, or git commit hash + * destination: Path to install the / of the git repo at when installing the rpm + """ + gitRpm = GitRpmBuild(gitRepo["rpmname"], gitRepo["rpmversion"], gitRepo["rpmrelease"], ["noarch"]) + try: + gitRpm.add_git_tarball(gitRepo) + gitRpm.do_make() + rpmfile = gitRpm.get_built_rpm("noarch") + shutil.move(rpmfile, dest) + except Exception as e: + log.error("Creating git repo rpm: %s", e) + raise RuntimeError("Creating git repo rpm: %s" % e) + finally: + gitRpm.cleanup_tmpdir() + + return os.path.basename(rpmfile)
+ +# Create the git rpms, if any, and return the path to the repo under results_dir +
[docs]def create_gitrpm_repo(results_dir, recipe): + """Create a dnf repository with the rpms from the recipe + + :param results_dir: Path to create the repository under + :type results_dir: str + :param recipe: The recipe to get the repos.git entries from + :type recipe: Recipe + :returns: Path to the dnf repository or "" + :rtype: str + + This function creates a dnf repository directory at results_dir+"repo/", + creates rpms for all of the repos.git entries in the recipe, runs createrepo_c + on the dnf repository so that Anaconda can use it, and returns the path to the + repository to the caller. + """ + if "repos" not in recipe or "git" not in recipe["repos"]: + return "" + + gitrepo = joinpaths(results_dir, "repo/") + if not os.path.exists(gitrepo): + os.makedirs(gitrepo) + for r in recipe["repos"]["git"]: + make_git_rpm(r, gitrepo) + cmd = ["createrepo_c", gitrepo] + log.debug(cmd) + try: + subprocess.check_output(cmd) + except subprocess.CalledProcessError as e: + log.error("Failed to create repo at %s: %s", gitrepo, e.output) + raise RuntimeError("Failed to create repo at %s" % gitrepo) + + return gitrepo
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/projects.html b/f29-branch/_modules/pylorax/api/projects.html new file mode 100644 index 00000000..0d538c67 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/projects.html @@ -0,0 +1,800 @@ + + + + + + + + + + + pylorax.api.projects — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.projects

+#
+# Copyright (C) 2017  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("lorax-composer")
+
+from configparser import ConfigParser
+import dnf
+from glob import glob
+import os
+import time
+
+from pylorax.api.bisect import insort_left
+
+TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
+
+
+
[docs]class ProjectsError(Exception): + pass
+ + +
[docs]def api_time(t): + """Convert time since epoch to a string + + :param t: Seconds since epoch + :type t: int + :returns: Time string + :rtype: str + """ + return time.strftime(TIME_FORMAT, time.localtime(t))
+ + +
[docs]def api_changelog(changelog): + """Convert the changelog to a string + + :param changelog: A list of time, author, string tuples. + :type changelog: tuple + :returns: The most recent changelog text or "" + :rtype: str + + This returns only the most recent changelog entry. + """ + try: + entry = changelog[0][2] + except IndexError: + entry = "" + return entry
+ + +
[docs]def pkg_to_project(pkg): + """Extract the details from a hawkey.Package object + + :param pkgs: hawkey.Package object with package details + :type pkgs: hawkey.Package + :returns: A dict with the name, summary, description, and url. + :rtype: dict + + upstream_vcs is hard-coded to UPSTREAM_VCS + """ + return {"name": pkg.name, + "summary": pkg.summary, + "description": pkg.description, + "homepage": pkg.url, + "upstream_vcs": "UPSTREAM_VCS"}
+ + +
[docs]def pkg_to_build(pkg): + """Extract the build details from a hawkey.Package object + + :param pkg: hawkey.Package object with package details + :type pkg: hawkey.Package + :returns: A dict with the build details, epoch, release, arch, build_time, changelog, ... + :rtype: dict + + metadata entries are hard-coded to {} + + Note that this only returns the build dict, it does not include the name, description, etc. + """ + return {"epoch": pkg.epoch, + "release": pkg.release, + "arch": pkg.arch, + "build_time": api_time(pkg.buildtime), + "changelog": "CHANGELOG_NEEDED", # XXX Not in hawkey.Package + "build_config_ref": "BUILD_CONFIG_REF", + "build_env_ref": "BUILD_ENV_REF", + "metadata": {}, + "source": {"license": pkg.license, + "version": pkg.version, + "source_ref": "SOURCE_REF", + "metadata": {}}}
+ + +
[docs]def pkg_to_project_info(pkg): + """Extract the details from a hawkey.Package object + + :param pkg: hawkey.Package object with package details + :type pkg: hawkey.Package + :returns: A dict with the project details, as well as epoch, release, arch, build_time, changelog, ... + :rtype: dict + + metadata entries are hard-coded to {} + """ + return {"name": pkg.name, + "summary": pkg.summary, + "description": pkg.description, + "homepage": pkg.url, + "upstream_vcs": "UPSTREAM_VCS", + "builds": [pkg_to_build(pkg)]}
+ + +
[docs]def pkg_to_dep(pkg): + """Extract the info from a hawkey.Package object + + :param pkg: A hawkey.Package object + :type pkg: hawkey.Package + :returns: A dict with name, epoch, version, release, arch + :rtype: dict + """ + return {"name": pkg.name, + "epoch": pkg.epoch, + "version": pkg.version, + "release": pkg.release, + "arch": pkg.arch}
+ + +
[docs]def proj_to_module(proj): + """Extract the name from a project_info dict + + :param pkg: dict with package details + :type pkg: dict + :returns: A dict with name, and group_type + :rtype: dict + + group_type is hard-coded to "rpm" + """ + return {"name": proj["name"], + "group_type": "rpm"}
+ + +
[docs]def dep_evra(dep): + """Return the epoch:version-release.arch for the dep + + :param dep: dependency dict + :type dep: dict + :returns: epoch:version-release.arch + :rtype: str + """ + if dep["epoch"] == 0: + return dep["version"]+"-"+dep["release"]+"."+dep["arch"] + else: + return str(dep["epoch"])+":"+dep["version"]+"-"+dep["release"]+"."+dep["arch"]
+ +
[docs]def dep_nevra(dep): + """Return the name-epoch:version-release.arch""" + return dep["name"]+"-"+dep_evra(dep)
+ + +
[docs]def projects_list(dbo): + """Return a list of projects + + :param dbo: dnf base object + :type dbo: dnf.Base + :returns: List of project info dicts with name, summary, description, homepage, upstream_vcs + :rtype: list of dicts + """ + return projects_info(dbo, None)
+ + +
[docs]def projects_info(dbo, project_names): + """Return details about specific projects + + :param dbo: dnf base object + :type dbo: dnf.Base + :param project_names: List of names of projects to get info about + :type project_names: str + :returns: List of project info dicts with pkg_to_project as well as epoch, version, release, etc. + :rtype: list of dicts + + If project_names is None it will return the full list of available packages + """ + if project_names: + pkgs = dbo.sack.query().available().filter(name__glob=project_names) + else: + pkgs = dbo.sack.query().available() + + # iterate over pkgs + # - if pkg.name isn't in the results yet, add pkg_to_project_info in sorted position + # - if pkg.name is already in results, get its builds. If the build for pkg is different + # in any way (version, arch, etc.) add it to the entry's builds list. If it is the same, + # skip it. + results = [] + results_names = {} + for p in pkgs: + if p.name.lower() not in results_names: + idx = insort_left(results, pkg_to_project_info(p), key=lambda p: p["name"].lower()) + results_names[p.name.lower()] = idx + else: + build = pkg_to_build(p) + if build not in results[results_names[p.name.lower()]]["builds"]: + results[results_names[p.name.lower()]]["builds"].append(build) + + return results
+ +def _depsolve(dbo, projects, groups): + """Add projects to a new transaction + + :param dbo: dnf base object + :type dbo: dnf.Base + :param projects: The projects and version globs to find the dependencies for + :type projects: List of tuples + :param groups: The groups to include in dependency solving + :type groups: List of str + :returns: None + :rtype: None + :raises: ProjectsError if there was a problem installing something + """ + # This resets the transaction and updates the cache. + # It is important that the cache always be synchronized because Anaconda will grab its own copy + # and if that is different the NEVRAs will not match and the build will fail. + dbo.reset(goal=True) + install_errors = [] + for name in groups: + try: + dbo.group_install(name, ["mandatory", "default"]) + except dnf.exceptions.MarkingError as e: + install_errors.append(("Group %s" % (name), str(e))) + + for name, version in projects: + # Find the best package matching the name + version glob + # dnf can return multiple packages if it is in more than 1 repository + query = dbo.sack.query().filterm(provides__glob=name) + if version: + query.filterm(version__glob=version) + + query.filterm(latest=1) + if not query: + install_errors.append(("%s-%s" % (name, version), "No match")) + continue + sltr = dnf.selector.Selector(dbo.sack).set(pkg=query) + + # NOTE: dnf says in near future there will be a "goal" attribute of Base class + # so yes, we're using a 'private' attribute here on purpose and with permission. + dbo._goal.install(select=sltr, optional=False) + + if install_errors: + raise ProjectsError("The following package(s) had problems: %s" % ",".join(["%s (%s)" % (pattern, err) for pattern, err in install_errors])) + +
[docs]def projects_depsolve(dbo, projects, groups): + """Return the dependencies for a list of projects + + :param dbo: dnf base object + :type dbo: dnf.Base + :param projects: The projects to find the dependencies for + :type projects: List of Strings + :param groups: The groups to include in dependency solving + :type groups: List of str + :returns: NEVRA's of the project and its dependencies + :rtype: list of dicts + :raises: ProjectsError if there was a problem installing something + """ + _depsolve(dbo, projects, groups) + + try: + dbo.resolve() + except dnf.exceptions.DepsolveError as e: + raise ProjectsError("There was a problem depsolving %s: %s" % (projects, str(e))) + + if len(dbo.transaction) == 0: + return [] + + return sorted(map(pkg_to_dep, dbo.transaction.install_set), key=lambda p: p["name"].lower())
+ + +
[docs]def estimate_size(packages, block_size=6144): + """Estimate the installed size of a package list + + :param packages: The packages to be installed + :type packages: list of hawkey.Package objects + :param block_size: The block size to use for rounding up file sizes. + :type block_size: int + :returns: The estimated size of installed packages + :rtype: int + + Estimating actual requirements is difficult without the actual file sizes, which + dnf doesn't provide access to. So use the file count and block size to estimate + a minimum size for each package. + """ + installed_size = 0 + for p in packages: + installed_size += len(p.files) * block_size + installed_size += p.installsize + return installed_size
+ + +
[docs]def projects_depsolve_with_size(dbo, projects, groups, with_core=True): + """Return the dependencies and installed size for a list of projects + + :param dbo: dnf base object + :type dbo: dnf.Base + :param project_names: The projects to find the dependencies for + :type project_names: List of Strings + :param groups: The groups to include in dependency solving + :type groups: List of str + :returns: installed size and a list of NEVRA's of the project and its dependencies + :rtype: tuple of (int, list of dicts) + :raises: ProjectsError if there was a problem installing something + """ + _depsolve(dbo, projects, groups) + + if with_core: + dbo.group_install("core", ['mandatory', 'default', 'optional']) + + try: + dbo.resolve() + except dnf.exceptions.DepsolveError as e: + raise ProjectsError("There was a problem depsolving %s: %s" % (projects, str(e))) + + if len(dbo.transaction) == 0: + return (0, []) + + installed_size = estimate_size(dbo.transaction.install_set) + deps = sorted(map(pkg_to_dep, dbo.transaction.install_set), key=lambda p: p["name"].lower()) + return (installed_size, deps)
+ + +
[docs]def modules_list(dbo, module_names): + """Return a list of modules + + :param dbo: dnf base object + :type dbo: dnf.Base + :param offset: Number of modules to skip + :type limit: int + :param limit: Maximum number of modules to return + :type limit: int + :returns: List of module information and total count + :rtype: tuple of a list of dicts and an Int + + Modules don't exist in RHEL7 so this only returns projects + and sets the type to "rpm" + + """ + # TODO - Figure out what to do with this for Fedora 'modules' + return list(map(proj_to_module, projects_info(dbo, module_names)))
+ +
[docs]def modules_info(dbo, module_names): + """Return details about a module, including dependencies + + :param dbo: dnf base object + :type dbo: dnf.Base + :param module_names: Names of the modules to get info about + :type module_names: str + :returns: List of dicts with module details and dependencies. + :rtype: list of dicts + """ + modules = projects_info(dbo, module_names) + + # Add the dependency info to each one + for module in modules: + module["dependencies"] = projects_depsolve(dbo, [(module["name"], "*.*")], []) + + return modules
+ +
[docs]def dnf_repo_to_file_repo(repo): + """Return a string representation of a DNF Repo object suitable for writing to a .repo file + + :param repo: DNF Repository + :type repo: dnf.RepoDict + :returns: A string + :rtype: str + + The DNF Repo.dump() function does not produce a string that can be used as a dnf .repo file, + it ouputs baseurl and gpgkey as python lists which DNF cannot read. So do this manually with + only the attributes we care about. + """ + repo_str = "[%s]\nname = %s\n" % (repo.id, repo.name) + if repo.metalink: + repo_str += "metalink = %s\n" % repo.metalink + elif repo.mirrorlist: + repo_str += "mirrorlist = %s\n" % repo.mirrorlist + elif repo.baseurl: + repo_str += "baseurl = %s\n" % repo.baseurl[0] + else: + raise RuntimeError("Repo has no baseurl, metalink, or mirrorlist") + + # proxy is optional + if repo.proxy: + repo_str += "proxy = %s\n" % repo.proxy + + repo_str += "sslverify = %s\n" % repo.sslverify + repo_str += "gpgcheck = %s\n" % repo.gpgcheck + if repo.gpgkey: + repo_str += "gpgkey = %s\n" % ",".join(repo.gpgkey) + + return repo_str
+ +
[docs]def repo_to_source(repo, system_source): + """Return a Weldr Source dict created from the DNF Repository + + :param repo: DNF Repository + :type repo: dnf.RepoDict + :param system_source: True if this source is an immutable system source + :type system_source: bool + :returns: A dict with Weldr Source fields filled in + :rtype: dict + + Example:: + + { + "check_gpg": true, + "check_ssl": true, + "gpgkey_url": [ + "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-28-x86_64" + ], + "name": "fedora", + "proxy": "http://proxy.brianlane.com:8123", + "system": true + "type": "yum-metalink", + "url": "https://mirrors.fedoraproject.org/metalink?repo=fedora-28&arch=x86_64" + } + + """ + source = {"name": repo.id, "system": system_source} + if repo.baseurl: + source["url"] = repo.baseurl[0] + source["type"] = "yum-baseurl" + elif repo.metalink: + source["url"] = repo.metalink + source["type"] = "yum-metalink" + elif repo.mirrorlist: + source["url"] = repo.mirrorlist + source["type"] = "yum-mirrorlist" + else: + raise RuntimeError("Repo has no baseurl, metalink, or mirrorlist") + + # proxy is optional + if repo.proxy: + source["proxy"] = repo.proxy + + if not repo.sslverify: + source["check_ssl"] = False + else: + source["check_ssl"] = True + + if not repo.gpgcheck: + source["check_gpg"] = False + else: + source["check_gpg"] = True + + if repo.gpgkey: + source["gpgkey_urls"] = list(repo.gpgkey) + + return source
+ +
[docs]def source_to_repo(source, dnf_conf): + """Return a dnf Repo object created from a source dict + + :param source: A Weldr source dict + :type source: dict + :returns: A dnf Repo object + :rtype: dnf.Repo + + Example:: + + { + "check_gpg": True, + "check_ssl": True, + "gpgkey_urls": [ + "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-28-x86_64" + ], + "name": "fedora", + "proxy": "http://proxy.brianlane.com:8123", + "system": True + "type": "yum-metalink", + "url": "https://mirrors.fedoraproject.org/metalink?repo=fedora-28&arch=x86_64" + } + + """ + repo = dnf.repo.Repo(source["name"], dnf_conf) + # This will allow errors to be raised so we can catch them + # without this they are logged, but the repo is silently disabled + repo.skip_if_unavailable = False + + if source["type"] == "yum-baseurl": + repo.baseurl = source["url"] + elif source["type"] == "yum-metalink": + repo.metalink = source["url"] + elif source["type"] == "yum-mirrorlist": + repo.mirrorlist = source["url"] + + if "proxy" in source: + repo.proxy = source["proxy"] + + if source["check_ssl"]: + repo.sslverify = True + else: + repo.sslverify = False + + if source["check_gpg"]: + repo.gpgcheck = True + else: + repo.gpgcheck = False + + if "gpgkey_urls" in source: + repo.gpgkey = tuple(source["gpgkey_urls"]) + + repo.enable() + + return repo
+ +
[docs]def get_source_ids(source_path): + """Return a list of the source ids in a file + + :param source_path: Full path and filename of the source (yum repo) file + :type source_path: str + :returns: A list of source id strings + :rtype: list of str + """ + if not os.path.exists(source_path): + return [] + + cfg = ConfigParser() + cfg.read(source_path) + return cfg.sections()
+ +
[docs]def get_repo_sources(source_glob): + """Return a list of sources from a directory of yum repositories + + :param source_glob: A glob to use to match the source files, including full path + :type source_glob: str + :returns: A list of the source ids in all of the matching files + :rtype: list of str + """ + sources = [] + for f in glob(source_glob): + sources.extend(get_source_ids(f)) + return sources
+ +
[docs]def delete_repo_source(source_glob, source_name): + """Delete a source from a repo file + + :param source_glob: A glob of the repo sources to search + :type source_glob: str + :returns: None + :raises: ProjectsError if there was a problem + + A repo file may have multiple sources in it, delete only the selected source. + If it is the last one in the file, delete the file. + + WARNING: This will delete ANY source, the caller needs to ensure that a system + source_name isn't passed to it. + """ + found = False + for f in glob(source_glob): + try: + cfg = ConfigParser() + cfg.read(f) + if source_name in cfg.sections(): + found = True + cfg.remove_section(source_name) + # If there are other sections, rewrite the file without the deleted one + if len(cfg.sections()) > 0: + with open(f, "w") as cfg_file: + cfg.write(cfg_file) + else: + # No sections left, just delete the file + os.unlink(f) + except Exception as e: + raise ProjectsError("Problem deleting repo source %s: %s" % (source_name, str(e))) + if not found: + raise ProjectsError("source %s not found" % source_name)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/queue.html b/f29-branch/_modules/pylorax/api/queue.html new file mode 100644 index 00000000..b19b4936 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/queue.html @@ -0,0 +1,892 @@ + + + + + + + + + + + pylorax.api.queue — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.queue

+# Copyright (C) 2018 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, see <http://www.gnu.org/licenses/>.
+#
+""" Functions to monitor compose queue and run anaconda"""
+import logging
+log = logging.getLogger("pylorax")
+
+import os
+import grp
+from glob import glob
+import multiprocessing as mp
+import pytoml as toml
+import pwd
+import shutil
+import subprocess
+from subprocess import Popen, PIPE
+import time
+
+from pylorax import find_templates
+from pylorax.api.compose import move_compose_results
+from pylorax.api.recipes import recipe_from_file
+from pylorax.api.timestamp import TS_CREATED, TS_STARTED, TS_FINISHED, write_timestamp, timestamp_dict
+from pylorax.base import DataHolder
+from pylorax.creator import run_creator
+from pylorax.sysutils import joinpaths
+
+
[docs]def check_queues(cfg): + """Check to make sure the new and run queue symlinks are correct + + :param cfg: Configuration settings + :type cfg: DataHolder + + Also check all of the existing results and make sure any with WAITING + set in STATUS have a symlink in queue/new/ + """ + # Remove broken symlinks from the new and run queues + queue_symlinks = glob(joinpaths(cfg.composer_dir, "queue/new/*")) + \ + glob(joinpaths(cfg.composer_dir, "queue/run/*")) + for link in queue_symlinks: + if not os.path.isdir(os.path.realpath(link)): + log.info("Removing broken symlink %s", link) + os.unlink(link) + + # Write FAILED to the STATUS of any run queue symlinks and remove them + for link in glob(joinpaths(cfg.composer_dir, "queue/run/*")): + log.info("Setting build %s to FAILED, and removing symlink from queue/run/", os.path.basename(link)) + open(joinpaths(link, "STATUS"), "w").write("FAILED\n") + os.unlink(link) + + # Check results STATUS messages + # - If STATUS is missing, set it to FAILED + # - RUNNING should be changed to FAILED + # - WAITING should have a symlink in the new queue + for link in glob(joinpaths(cfg.composer_dir, "results/*")): + if not os.path.exists(joinpaths(link, "STATUS")): + open(joinpaths(link, "STATUS"), "w").write("FAILED\n") + continue + + status = open(joinpaths(link, "STATUS")).read().strip() + if status == "RUNNING": + log.info("Setting build %s to FAILED", os.path.basename(link)) + open(joinpaths(link, "STATUS"), "w").write("FAILED\n") + elif status == "WAITING": + if not os.path.islink(joinpaths(cfg.composer_dir, "queue/new/", os.path.basename(link))): + log.info("Creating missing symlink to new build %s", os.path.basename(link)) + os.symlink(link, joinpaths(cfg.composer_dir, "queue/new/", os.path.basename(link)))
+ +
[docs]def start_queue_monitor(cfg, uid, gid): + """Start the queue monitor as a mp process + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uid: User ID that owns the queue + :type uid: int + :param gid: Group ID that owns the queue + :type gid: int + :returns: None + """ + lib_dir = cfg.get("composer", "lib_dir") + share_dir = cfg.get("composer", "share_dir") + tmp = cfg.get("composer", "tmp") + monitor_cfg = DataHolder(composer_dir=lib_dir, share_dir=share_dir, uid=uid, gid=gid, tmp=tmp) + p = mp.Process(target=monitor, args=(monitor_cfg,)) + p.daemon = True + p.start()
+ +
[docs]def monitor(cfg): + """Monitor the queue for new compose requests + + :param cfg: Configuration settings + :type cfg: DataHolder + :returns: Does not return + + The queue has 2 subdirectories, new and run. When a compose is ready to be run + a symlink to the uniquely named results directory should be placed in ./queue/new/ + + When the it is ready to be run (it is checked every 30 seconds or after a previous + compose is finished) the symlink will be moved into ./queue/run/ and a STATUS file + will be created in the results directory. + + STATUS can contain one of: WAITING, RUNNING, FINISHED, FAILED + + If the system is restarted while a compose is running it will move any old symlinks + from ./queue/run/ to ./queue/new/ and rerun them. + """ + def queue_sort(uuid): + """Sort the queue entries by their mtime, not their names""" + return os.stat(joinpaths(cfg.composer_dir, "queue/new", uuid)).st_mtime + + check_queues(cfg) + while True: + uuids = sorted(os.listdir(joinpaths(cfg.composer_dir, "queue/new")), key=queue_sort) + + # Pick the oldest and move it into ./run/ + if not uuids: + # No composes left to process, sleep for a bit + time.sleep(5) + else: + src = joinpaths(cfg.composer_dir, "queue/new", uuids[0]) + dst = joinpaths(cfg.composer_dir, "queue/run", uuids[0]) + try: + os.rename(src, dst) + except OSError: + # The symlink may vanish if uuid_cancel() has been called + continue + + log.info("Starting new compose: %s", dst) + open(joinpaths(dst, "STATUS"), "w").write("RUNNING\n") + + try: + make_compose(cfg, os.path.realpath(dst)) + log.info("Finished building %s, results are in %s", dst, os.path.realpath(dst)) + open(joinpaths(dst, "STATUS"), "w").write("FINISHED\n") + write_timestamp(dst, TS_FINISHED) + except Exception: + import traceback + log.error("traceback: %s", traceback.format_exc()) + +# TODO - Write the error message to an ERROR-LOG file to include with the status +# log.error("Error running compose: %s", e) + open(joinpaths(dst, "STATUS"), "w").write("FAILED\n") + write_timestamp(dst, TS_FINISHED) + + os.unlink(dst)
+ +
[docs]def make_compose(cfg, results_dir): + """Run anaconda with the final-kickstart.ks from results_dir + + :param cfg: Configuration settings + :type cfg: DataHolder + :param results_dir: The directory containing the metadata and results for the build + :type results_dir: str + :returns: Nothing + :raises: May raise various exceptions + + This takes the final-kickstart.ks, and the settings in config.toml and runs Anaconda + in no-virt mode (directly on the host operating system). Exceptions should be caught + at the higer level. + + If there is a failure, the build artifacts will be cleaned up, and any logs will be + moved into logs/anaconda/ and their ownership will be set to the user from the cfg + object. + """ + + # Check on the ks's presence + ks_path = joinpaths(results_dir, "final-kickstart.ks") + if not os.path.exists(ks_path): + raise RuntimeError("Missing kickstart file at %s" % ks_path) + + # The anaconda logs are copied into ./anaconda/ in this directory + log_dir = joinpaths(results_dir, "logs/") + if not os.path.exists(log_dir): + os.makedirs(log_dir) + + # Load the compose configuration + cfg_path = joinpaths(results_dir, "config.toml") + if not os.path.exists(cfg_path): + raise RuntimeError("Missing config.toml for %s" % results_dir) + cfg_dict = toml.loads(open(cfg_path, "r").read()) + + # The keys in cfg_dict correspond to the arguments setup in livemedia-creator + # keys that define what to build should be setup in compose_args, and keys with + # defaults should be setup here. + + # Make sure that image_name contains no path components + cfg_dict["image_name"] = os.path.basename(cfg_dict["image_name"]) + + # Only support novirt installation, set some other defaults + cfg_dict["no_virt"] = True + cfg_dict["disk_image"] = None + cfg_dict["fs_image"] = None + cfg_dict["keep_image"] = False + cfg_dict["domacboot"] = False + cfg_dict["anaconda_args"] = "" + cfg_dict["proxy"] = "" + cfg_dict["armplatform"] = "" + cfg_dict["squashfs_args"] = None + + cfg_dict["lorax_templates"] = find_templates(cfg.share_dir) + cfg_dict["tmp"] = cfg.tmp + cfg_dict["dracut_args"] = None # Use default args for dracut + + # TODO How to support other arches? + cfg_dict["arch"] = None + + # Compose things in a temporary directory inside the results directory + cfg_dict["result_dir"] = joinpaths(results_dir, "compose") + os.makedirs(cfg_dict["result_dir"]) + + install_cfg = DataHolder(**cfg_dict) + + # Some kludges for the 99-copy-logs %post, failure in it will crash the build + for f in ["/tmp/NOSAVE_INPUT_KS", "/tmp/NOSAVE_LOGS"]: + open(f, "w") + + # Placing a CANCEL file in the results directory will make execWithRedirect send anaconda a SIGTERM + def cancel_build(): + return os.path.exists(joinpaths(results_dir, "CANCEL")) + + log.debug("cfg = %s", install_cfg) + try: + test_path = joinpaths(results_dir, "TEST") + write_timestamp(results_dir, TS_STARTED) + if os.path.exists(test_path): + # Pretend to run the compose + time.sleep(5) + try: + test_mode = int(open(test_path, "r").read()) + except Exception: + test_mode = 1 + if test_mode == 1: + raise RuntimeError("TESTING FAILED compose") + else: + open(joinpaths(results_dir, install_cfg.image_name), "w").write("TEST IMAGE") + else: + run_creator(install_cfg, cancel_func=cancel_build) + + # Extract the results of the compose into results_dir and cleanup the compose directory + move_compose_results(install_cfg, results_dir) + finally: + # Make sure any remaining temporary directories are removed (eg. if there was an exception) + for d in glob(joinpaths(cfg.tmp, "lmc-*")): + if os.path.isdir(d): + shutil.rmtree(d) + elif os.path.isfile(d): + os.unlink(d) + + # Make sure that everything under the results directory is owned by the user + user = pwd.getpwuid(cfg.uid).pw_name + group = grp.getgrgid(cfg.gid).gr_name + log.debug("Install finished, chowning results to %s:%s", user, group) + subprocess.call(["chown", "-R", "%s:%s" % (user, group), results_dir])
+ +
[docs]def get_compose_type(results_dir): + """Return the type of composition. + + :param results_dir: The directory containing the metadata and results for the build + :type results_dir: str + :returns: The type of compose (eg. 'tar') + :rtype: str + :raises: RuntimeError if no kickstart template can be found. + """ + # Should only be 2 kickstarts, the final-kickstart.ks and the template + t = [os.path.basename(ks)[:-3] for ks in glob(joinpaths(results_dir, "*.ks")) + if "final-kickstart" not in ks] + if len(t) != 1: + raise RuntimeError("Cannot find ks template for build %s" % os.path.basename(results_dir)) + return t[0]
+ +
[docs]def compose_detail(results_dir): + """Return details about the build. + + :param results_dir: The directory containing the metadata and results for the build + :type results_dir: str + :returns: A dictionary with details about the compose + :rtype: dict + :raises: IOError if it cannot read the directory, STATUS, or blueprint file. + + The following details are included in the dict: + + * id - The uuid of the comoposition + * queue_status - The final status of the composition (FINISHED or FAILED) + * compose_type - The type of output generated (tar, iso, etc.) + * blueprint - Blueprint name + * version - Blueprint version + * image_size - Size of the image, if finished. 0 otherwise. + + Various timestamps are also included in the dict. These are all Unix UTC timestamps. + It is possible for these timestamps to not always exist, in which case they will be + None in Python (or null in JSON). The following timestamps are included: + + * job_created - When the user submitted the compose + * job_started - Anaconda started running + * job_finished - Job entered FINISHED or FAILED state + """ + build_id = os.path.basename(os.path.abspath(results_dir)) + status = open(joinpaths(results_dir, "STATUS")).read().strip() + blueprint = recipe_from_file(joinpaths(results_dir, "blueprint.toml")) + + compose_type = get_compose_type(results_dir) + + image_path = get_image_name(results_dir)[1] + if status == "FINISHED" and os.path.exists(image_path): + image_size = os.stat(image_path).st_size + else: + image_size = 0 + + times = timestamp_dict(results_dir) + + return {"id": build_id, + "queue_status": status, + "job_created": times.get(TS_CREATED), + "job_started": times.get(TS_STARTED), + "job_finished": times.get(TS_FINISHED), + "compose_type": compose_type, + "blueprint": blueprint["name"], + "version": blueprint["version"], + "image_size": image_size + }
+ +
[docs]def queue_status(cfg): + """Return details about what is in the queue. + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :returns: A list of the new composes, and a list of the running composes + :rtype: dict + + This returns a dict with 2 lists. "new" is the list of uuids that are waiting to be built, + and "run" has the uuids that are being built (currently limited to 1 at a time). + """ + queue_dir = joinpaths(cfg.get("composer", "lib_dir"), "queue") + new_queue = [os.path.realpath(p) for p in glob(joinpaths(queue_dir, "new/*"))] + run_queue = [os.path.realpath(p) for p in glob(joinpaths(queue_dir, "run/*"))] + + new_details = [] + for n in new_queue: + try: + d = compose_detail(n) + except IOError: + continue + new_details.append(d) + + run_details = [] + for r in run_queue: + try: + d = compose_detail(r) + except IOError: + continue + run_details.append(d) + + return { + "new": new_details, + "run": run_details + }
+ +
[docs]def uuid_status(cfg, uuid): + """Return the details of a specific UUID compose + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: Details about the build + :rtype: dict or None + + Returns the same dict as `compose_details()` + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + try: + return compose_detail(uuid_dir) + except IOError: + return None
+ +
[docs]def build_status(cfg, status_filter=None): + """Return the details of finished or failed builds + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param status_filter: What builds to return. None == all, "FINISHED", or "FAILED" + :type status_filter: str + :returns: A list of the build details (from compose_details) + :rtype: list of dicts + + This returns a list of build details for each of the matching builds on the + system. It does not return the status of builds that have not been finished. + Use queue_status() for those. + """ + if status_filter: + status_filter = [status_filter] + else: + status_filter = ["FINISHED", "FAILED"] + + results = [] + result_dir = joinpaths(cfg.get("composer", "lib_dir"), "results") + for build in glob(result_dir + "/*"): + log.debug("Checking status of build %s", build) + + try: + status = open(joinpaths(build, "STATUS"), "r").read().strip() + if status in status_filter: + results.append(compose_detail(build)) + except IOError: + pass + return results
+ +
[docs]def uuid_cancel(cfg, uuid): + """Cancel a build and delete its results + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: True if it was canceled and deleted + :rtype: bool + + Only call this if the build status is WAITING or RUNNING + """ + cancel_path = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid, "CANCEL") + if os.path.exists(cancel_path): + log.info("Cancel has already been requested for %s", uuid) + return False + + # This status can change (and probably will) while it is in the middle of doing this: + # It can move from WAITING -> RUNNING or it can move from RUNNING -> FINISHED|FAILED + + # If it is in WAITING remove the symlink and then check to make sure it didn't show up + # in the run queue + queue_dir = joinpaths(cfg.get("composer", "lib_dir"), "queue") + uuid_new = joinpaths(queue_dir, "new", uuid) + if os.path.exists(uuid_new): + try: + os.unlink(uuid_new) + except OSError: + # The symlink may vanish if the queue monitor started the build + pass + uuid_run = joinpaths(queue_dir, "run", uuid) + if not os.path.exists(uuid_run): + # Make sure the build is still in the waiting state + status = uuid_status(cfg, uuid) + if status is None or status["queue_status"] == "WAITING": + # Successfully removed it before the build started + return uuid_delete(cfg, uuid) + + # At this point the build has probably started. Write to the CANCEL file. + open(cancel_path, "w").write("\n") + + # Wait for status to move to FAILED or FINISHED + started = time.time() + while True: + status = uuid_status(cfg, uuid) + if status is None or status["queue_status"] == "FAILED": + break + elif status is not None and status["queue_status"] == "FINISHED": + # The build finished successfully, no point in deleting it now + return False + + # Is this taking too long? Exit anyway and try to cleanup. + if time.time() > started + (10 * 60): + log.error("Failed to cancel the build of %s", uuid) + break + + time.sleep(5) + + # Remove the partial results + uuid_delete(cfg, uuid)
+ +
[docs]def uuid_delete(cfg, uuid): + """Delete all of the results from a compose + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: True if it was deleted + :rtype: bool + :raises: This will raise an error if the delete failed + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + if not uuid_dir or len(uuid_dir) < 10: + raise RuntimeError("Directory length is too short: %s" % uuid_dir) + shutil.rmtree(uuid_dir) + return True
+ +
[docs]def uuid_info(cfg, uuid): + """Return information about the composition + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: dictionary of information about the composition or None + :rtype: dict + :raises: RuntimeError if there was a problem + + This will return a dict with the following fields populated: + + * id - The uuid of the comoposition + * config - containing the configuration settings used to run Anaconda + * blueprint - The depsolved blueprint used to generate the kickstart + * commit - The (local) git commit hash for the blueprint used + * deps - The NEVRA of all of the dependencies used in the composition + * compose_type - The type of output generated (tar, iso, etc.) + * queue_status - The final status of the composition (FINISHED or FAILED) + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + if not os.path.exists(uuid_dir): + return None + + # Load the compose configuration + cfg_path = joinpaths(uuid_dir, "config.toml") + if not os.path.exists(cfg_path): + raise RuntimeError("Missing config.toml for %s" % uuid) + cfg_dict = toml.loads(open(cfg_path, "r").read()) + + frozen_path = joinpaths(uuid_dir, "frozen.toml") + if not os.path.exists(frozen_path): + raise RuntimeError("Missing frozen.toml for %s" % uuid) + frozen_dict = toml.loads(open(frozen_path, "r").read()) + + deps_path = joinpaths(uuid_dir, "deps.toml") + if not os.path.exists(deps_path): + raise RuntimeError("Missing deps.toml for %s" % uuid) + deps_dict = toml.loads(open(deps_path, "r").read()) + + details = compose_detail(uuid_dir) + + commit_path = joinpaths(uuid_dir, "COMMIT") + if not os.path.exists(commit_path): + raise RuntimeError("Missing commit hash for %s" % uuid) + commit_id = open(commit_path, "r").read().strip() + + return {"id": uuid, + "config": cfg_dict, + "blueprint": frozen_dict, + "commit": commit_id, + "deps": deps_dict, + "compose_type": details["compose_type"], + "queue_status": details["queue_status"], + "image_size": details["image_size"] + }
+ +
[docs]def uuid_tar(cfg, uuid, metadata=False, image=False, logs=False): + """Return a tar of the build data + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :param metadata: Set to true to include all the metadata needed to reproduce the build + :type metadata: bool + :param image: Set to true to include the output image + :type image: bool + :param logs: Set to true to include the logs from the build + :type logs: bool + :returns: A stream of bytes from tar + :rtype: A generator + :raises: RuntimeError if there was a problem (eg. missing config file) + + This yields an uncompressed tar's data to the caller. It includes + the selected data to the caller by returning the Popen stdout from the tar process. + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + if not os.path.exists(uuid_dir): + raise RuntimeError("%s is not a valid build_id" % uuid) + + # Load the compose configuration + cfg_path = joinpaths(uuid_dir, "config.toml") + if not os.path.exists(cfg_path): + raise RuntimeError("Missing config.toml for %s" % uuid) + cfg_dict = toml.loads(open(cfg_path, "r").read()) + image_name = cfg_dict["image_name"] + + def include_file(f): + if f.endswith("/logs"): + return logs + if f.endswith(image_name): + return image + return metadata + filenames = [os.path.basename(f) for f in glob(joinpaths(uuid_dir, "*")) if include_file(f)] + + tar = Popen(["tar", "-C", uuid_dir, "-cf-"] + filenames, stdout=PIPE) + return tar.stdout
+ +
[docs]def uuid_image(cfg, uuid): + """Return the filename and full path of the build's image file + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: The image filename and full path + :rtype: tuple of strings + :raises: RuntimeError if there was a problem (eg. invalid uuid, missing config file) + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + return get_image_name(uuid_dir)
+ +
[docs]def get_image_name(uuid_dir): + """Return the filename and full path of the build's image file + + :param uuid: The UUID of the build + :type uuid: str + :returns: The image filename and full path + :rtype: tuple of strings + :raises: RuntimeError if there was a problem (eg. invalid uuid, missing config file) + """ + uuid = os.path.basename(os.path.abspath(uuid_dir)) + if not os.path.exists(uuid_dir): + raise RuntimeError("%s is not a valid build_id" % uuid) + + # Load the compose configuration + cfg_path = joinpaths(uuid_dir, "config.toml") + if not os.path.exists(cfg_path): + raise RuntimeError("Missing config.toml for %s" % uuid) + cfg_dict = toml.loads(open(cfg_path, "r").read()) + image_name = cfg_dict["image_name"] + + return (image_name, joinpaths(uuid_dir, image_name))
+ +
[docs]def uuid_log(cfg, uuid, size=1024): + """Return `size` kbytes from the end of the anaconda.log + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :param size: Number of kbytes to read. Default is 1024 + :type size: int + :returns: Up to `size` kbytes from the end of the log + :rtype: str + :raises: RuntimeError if there was a problem (eg. no log file available) + + This function tries to return lines from the end of the log, it will + attempt to start on a line boundry, and may return less than `size` kbytes. + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + if not os.path.exists(uuid_dir): + raise RuntimeError("%s is not a valid build_id" % uuid) + + # While a build is running the logs will be in /tmp/anaconda.log and when it + # has finished they will be in the results directory + status = uuid_status(cfg, uuid) + if status is None: + raise RuntimeError("Status is missing for %s" % uuid) + + if status["queue_status"] == "RUNNING": + log_path = "/tmp/anaconda.log" + else: + log_path = joinpaths(uuid_dir, "logs", "anaconda", "anaconda.log") + if not os.path.exists(log_path): + raise RuntimeError("No anaconda.log available.") + + with open(log_path, "r") as f: + f.seek(0, 2) + end = f.tell() + if end < 1024 * size: + f.seek(0, 0) + else: + f.seek(end - (1024 * size)) + # Find the start of the next line and return the rest + f.readline() + return f.read()
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/recipes.html b/f29-branch/_modules/pylorax/api/recipes.html new file mode 100644 index 00000000..91317c62 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/recipes.html @@ -0,0 +1,1236 @@ + + + + + + + + + + + pylorax.api.recipes — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.recipes

+#
+# Copyright (C) 2017-2019  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, see <http://www.gnu.org/licenses/>.
+#
+
+import gi
+gi.require_version("Ggit", "1.0")
+from gi.repository import Ggit as Git
+from gi.repository import Gio
+from gi.repository import GLib
+
+import os
+import pytoml as toml
+import semantic_version as semver
+
+from pylorax.api.projects import dep_evra
+from pylorax.base import DataHolder
+from pylorax.sysutils import joinpaths
+
+
+
[docs]class CommitTimeValError(Exception): + pass
+ +
[docs]class RecipeFileError(Exception): + pass
+ +
[docs]class RecipeError(Exception): + pass
+ + +
[docs]class Recipe(dict): + """A Recipe of package and modules + + This is a subclass of dict that enforces the constructor arguments + and adds a .filename property to return the recipe's filename, + and a .toml() function to return the recipe as a TOML string. + """ + def __init__(self, name, description, version, modules, packages, groups, customizations=None, gitrepos=None): + # Check that version is empty or semver compatible + if version: + semver.Version(version) + + # Make sure modules, packages, and groups are listed by their case-insensitive names + if modules is not None: + modules = sorted(modules, key=lambda m: m["name"].lower()) + if packages is not None: + packages = sorted(packages, key=lambda p: p["name"].lower()) + if groups is not None: + groups = sorted(groups, key=lambda g: g["name"].lower()) + + # Only support [[repos.git]] for now + if gitrepos is not None: + repos = {"git": sorted(gitrepos, key=lambda g: g["repo"].lower())} + else: + repos = None + dict.__init__(self, name=name, + description=description, + version=version, + modules=modules, + packages=packages, + groups=groups, + customizations=customizations, + repos=repos) + + # We don't want customizations=None to show up in the TOML so remove it + if customizations is None: + del self["customizations"] + + # Don't include empty repos or repos.git + if repos is None or not repos["git"]: + del self["repos"] + + @property + def package_names(self): + """Return the names of the packages""" + return [p["name"] for p in self["packages"] or []] + + @property + def package_nver(self): + """Return the names and version globs of the packages""" + return [(p["name"], p["version"]) for p in self["packages"] or []] + + @property + def module_names(self): + """Return the names of the modules""" + return [m["name"] for m in self["modules"] or []] + + @property + def module_nver(self): + """Return the names and version globs of the modules""" + return [(m["name"], m["version"]) for m in self["modules"] or []] + + @property + def group_names(self): + """Return the names of the groups. Groups do not have versions.""" + return map(lambda g: g["name"], self["groups"] or []) + + @property + def filename(self): + """Return the Recipe's filename + + Replaces spaces in the name with '-' and appends .toml + """ + return recipe_filename(self.get("name")) + +
[docs] def toml(self): + """Return the Recipe in TOML format""" + return toml.dumps(self)
+ +
[docs] def bump_version(self, old_version=None): + """semver recipe version number bump + + :param old_version: An optional old version number + :type old_version: str + :returns: The new version number or None + :rtype: str + :raises: ValueError + + If neither have a version, 0.0.1 is returned + If there is no old version the new version is checked and returned + If there is no new version, but there is a old one, bump its patch level + If the old and new versions are the same, bump the patch level + If they are different, check and return the new version + """ + new_version = self.get("version") + if not new_version and not old_version: + self["version"] = "0.0.1" + + elif new_version and not old_version: + semver.Version(new_version) + self["version"] = new_version + + elif not new_version or new_version == old_version: + new_version = str(semver.Version(old_version).next_patch()) + self["version"] = new_version + + else: + semver.Version(new_version) + self["version"] = new_version + + # Return the new version + return str(semver.Version(self["version"]))
+ +
[docs] def freeze(self, deps): + """ Return a new Recipe with full module and package NEVRA + + :param deps: A list of dependency NEVRA to use to fill in the modules and packages + :type deps: list( + :returns: A new Recipe object + :rtype: Recipe + """ + module_names = self.module_names + package_names = self.package_names + group_names = self.group_names + + new_modules = [] + new_packages = [] + new_groups = [] + for dep in deps: + if dep["name"] in package_names: + new_packages.append(RecipePackage(dep["name"], dep_evra(dep))) + elif dep["name"] in module_names: + new_modules.append(RecipeModule(dep["name"], dep_evra(dep))) + elif dep["name"] in group_names: + new_groups.append(RecipeGroup(dep["name"])) + if "customizations" in self: + customizations = self["customizations"] + else: + customizations = None + if "repos" in self and "git" in self["repos"]: + gitrepos = self["repos"]["git"] + else: + gitrepos = None + + return Recipe(self["name"], self["description"], self["version"], + new_modules, new_packages, new_groups, customizations, gitrepos)
+ +
[docs]class RecipeModule(dict): + def __init__(self, name, version): + dict.__init__(self, name=name, version=version)
+ +
[docs]class RecipePackage(RecipeModule): + pass
+ +
[docs]class RecipeGroup(dict): + def __init__(self, name): + dict.__init__(self, name=name)
+ +
[docs]def NewRecipeGit(toml_dict): + """Create a RecipeGit object from fields in a TOML dict + + :param rpmname: Name of the rpm to create, also used as the prefix name in the tar archive + :type rpmname: str + :param rpmversion: Version of the rpm, eg. "1.0.0" + :type rpmversion: str + :param rpmrelease: Release of the rpm, eg. "1" + :type rpmrelease: str + :param summary: Summary string for the rpm + :type summary: str + :param repo: URL of the get repo to clone and create the archive from + :type repo: str + :param ref: Git reference to check out. eg. origin/branch-name, git tag, or git commit hash + :type ref: str + :param destination: Path to install the / of the git repo at when installing the rpm + :type destination: str + :returns: A populated RecipeGit object + :rtype: RecipeGit + + The TOML should look like this:: + + [[repos.git]] + rpmname="server-config" + rpmversion="1.0" + rpmrelease="1" + summary="Setup files for server deployment" + repo="PATH OF GIT REPO TO CLONE" + ref="v1.0" + destination="/opt/server/" + + Note that the repo path supports anything that git supports, file://, https://, http:// + + Currently there is no support for authentication + """ + return RecipeGit(toml_dict.get("rpmname"), + toml_dict.get("rpmversion"), + toml_dict.get("rpmrelease"), + toml_dict.get("summary", ""), + toml_dict.get("repo"), + toml_dict.get("ref"), + toml_dict.get("destination"))
+ +
[docs]class RecipeGit(dict): + def __init__(self, rpmname, rpmversion, rpmrelease, summary, repo, ref, destination): + dict.__init__(self, rpmname=rpmname, rpmversion=rpmversion, rpmrelease=rpmrelease, + summary=summary, repo=repo, ref=ref, destination=destination)
+ +
[docs]def recipe_from_file(recipe_path): + """Return a recipe file as a Recipe object + + :param recipe_path: Path to the recipe fila + :type recipe_path: str + :returns: A Recipe object + :rtype: Recipe + """ + with open(recipe_path, 'rb') as f: + return recipe_from_toml(f.read())
+ +
[docs]def recipe_from_toml(recipe_str): + """Create a Recipe object from a toml string. + + :param recipe_str: The Recipe TOML string + :type recipe_str: str + :returns: A Recipe object + :rtype: Recipe + :raises: TomlError + """ + recipe_dict = toml.loads(recipe_str) + return recipe_from_dict(recipe_dict)
+ +
[docs]def recipe_from_dict(recipe_dict): + """Create a Recipe object from a plain dict. + + :param recipe_dict: A plain dict of the recipe + :type recipe_dict: dict + :returns: A Recipe object + :rtype: Recipe + :raises: RecipeError + """ + # Make RecipeModule objects from the toml + # The TOML may not have modules or packages in it. Set them to None in this case + try: + if recipe_dict.get("modules"): + modules = [RecipeModule(m.get("name"), m.get("version")) for m in recipe_dict["modules"]] + else: + modules = [] + if recipe_dict.get("packages"): + packages = [RecipePackage(p.get("name"), p.get("version")) for p in recipe_dict["packages"]] + else: + packages = [] + if recipe_dict.get("groups"): + groups = [RecipeGroup(g.get("name")) for g in recipe_dict["groups"]] + else: + groups = [] + if recipe_dict.get("repos") and recipe_dict.get("repos").get("git"): + gitrepos = [NewRecipeGit(r) for r in recipe_dict["repos"]["git"]] + else: + gitrepos = [] + name = recipe_dict["name"] + description = recipe_dict["description"] + version = recipe_dict.get("version", None) + customizations = recipe_dict.get("customizations", None) + + # [customizations] was incorrectly documented at first, so we have to support using it + # as [[customizations]] by grabbing the first element. + if isinstance(customizations, list): + customizations = customizations[0] + + except KeyError as e: + raise RecipeError("There was a problem parsing the recipe: %s" % str(e)) + + return Recipe(name, description, version, modules, packages, groups, customizations, gitrepos)
+ +
[docs]def gfile(path): + """Convert a string path to GFile for use with Git""" + return Gio.file_new_for_path(path)
+ +
[docs]def recipe_filename(name): + """Return the toml filename for a recipe + + Replaces spaces with '-' and appends '.toml' + """ + # XXX Raise and error if this is empty? + return name.replace(" ", "-") + ".toml"
+ +
[docs]def head_commit(repo, branch): + """Get the branch's HEAD Commit Object + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :returns: Branch's head commit + :rtype: Git.Commit + :raises: Can raise errors from Ggit + """ + branch_obj = repo.lookup_branch(branch, Git.BranchType.LOCAL) + commit_id = branch_obj.get_target() + return repo.lookup(commit_id, Git.Commit)
+ +
[docs]def prepare_commit(repo, branch, builder): + """Prepare for a commit + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param builder: instance of TreeBuilder + :type builder: TreeBuilder + :returns: (Tree, Sig, Ref) + :rtype: tuple + :raises: Can raise errors from Ggit + """ + tree_id = builder.write() + tree = repo.lookup(tree_id, Git.Tree) + sig = Git.Signature.new_now("bdcs-api-server", "user-email") + ref = "refs/heads/%s" % branch + return (tree, sig, ref)
+ +
[docs]def open_or_create_repo(path): + """Open an existing repo, or create a new one + + :param path: path to recipe directory + :type path: string + :returns: A repository object + :rtype: Git.Repository + :raises: Can raise errors from Ggit + + A bare git repo will be created in the git directory of the specified path. + If a repo already exists it will be opened and returned instead of + creating a new one. + """ + Git.init() + git_path = joinpaths(path, "git") + if os.path.exists(joinpaths(git_path, "HEAD")): + return Git.Repository.open(gfile(git_path)) + + repo = Git.Repository.init_repository(gfile(git_path), True) + + # Make an initial empty commit + sig = Git.Signature.new_now("bdcs-api-server", "user-email") + tree_id = repo.get_index().write_tree() + tree = repo.lookup(tree_id, Git.Tree) + repo.create_commit("HEAD", sig, sig, "UTF-8", "Initial Recipe repository commit", tree, []) + return repo
+ +
[docs]def write_commit(repo, branch, filename, message, content): + """Make a new commit to a repository's branch + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: full path of the file to add + :type filename: str + :param message: The commit message + :type message: str + :param content: The data to write + :type content: str + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit + """ + try: + parent_commit = head_commit(repo, branch) + except GLib.GError: + # Branch doesn't exist, make a new one based on master + master_head = head_commit(repo, "master") + repo.create_branch(branch, master_head, 0) + parent_commit = head_commit(repo, branch) + + parent_commit = head_commit(repo, branch) + blob_id = repo.create_blob_from_buffer(content.encode("UTF-8")) + + # Use treebuilder to make a new entry for this filename and blob + parent_tree = parent_commit.get_tree() + builder = repo.create_tree_builder_from_tree(parent_tree) + builder.insert(filename, blob_id, Git.FileMode.BLOB) + (tree, sig, ref) = prepare_commit(repo, branch, builder) + return repo.create_commit(ref, sig, sig, "UTF-8", message, tree, [parent_commit])
+ +
[docs]def read_commit_spec(repo, spec): + """Return the raw content of the blob specified by the spec + + :param repo: Open repository + :type repo: Git.Repository + :param spec: Git revparse spec + :type spec: str + :returns: Contents of the commit + :rtype: str + :raises: Can raise errors from Ggit + + eg. To read the README file from master the spec is "master:README" + """ + commit_id = repo.revparse(spec).get_id() + blob = repo.lookup(commit_id, Git.Blob) + return blob.get_raw_content()
+ +
[docs]def read_commit(repo, branch, filename, commit=None): + """Return the contents of a file on a specific branch or commit. + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: filename to read + :type filename: str + :param commit: Optional commit hash + :type commit: str + :returns: The commit id, and the contents of the commit + :rtype: tuple(str, str) + :raises: Can raise errors from Ggit + + If no commit is passed the master:filename is returned, otherwise it will be + commit:filename + """ + if not commit: + # Find the most recent commit for filename on the selected branch + commits = list_commits(repo, branch, filename, 1) + if not commits: + raise RecipeError("No commits for %s on the %s branch." % (filename, branch)) + commit = commits[0].commit + return (commit, read_commit_spec(repo, "%s:%s" % (commit, filename)))
+ +
[docs]def read_recipe_commit(repo, branch, recipe_name, commit=None): + """Read a recipe commit from git and return a Recipe object + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to read + :type recipe_name: str + :param commit: Optional commit hash + :type commit: str + :returns: A Recipe object + :rtype: Recipe + :raises: Can raise errors from Ggit + + If no commit is passed the master:filename is returned, otherwise it will be + commit:filename + """ + if not repo_file_exists(repo, branch, recipe_filename(recipe_name)): + raise RecipeFileError("Unknown blueprint") + + (_, recipe_toml) = read_commit(repo, branch, recipe_filename(recipe_name), commit) + return recipe_from_toml(recipe_toml)
+ +
[docs]def read_recipe_and_id(repo, branch, recipe_name, commit=None): + """Read a recipe commit and its id from git + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to read + :type recipe_name: str + :param commit: Optional commit hash + :type commit: str + :returns: The commit id, and a Recipe object + :rtype: tuple(str, Recipe) + :raises: Can raise errors from Ggit + + If no commit is passed the master:filename is returned, otherwise it will be + commit:filename + """ + (commit_id, recipe_toml) = read_commit(repo, branch, recipe_filename(recipe_name), commit) + return (commit_id, recipe_from_toml(recipe_toml))
+ +
[docs]def list_branch_files(repo, branch): + """Return a sorted list of the files on the branch HEAD + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :returns: A sorted list of the filenames + :rtype: list(str) + :raises: Can raise errors from Ggit + """ + commit = head_commit(repo, branch).get_id().to_string() + return list_commit_files(repo, commit)
+ +
[docs]def list_commit_files(repo, commit): + """Return a sorted list of the files on a commit + + :param repo: Open repository + :type repo: Git.Repository + :param commit: The commit hash to list + :type commit: str + :returns: A sorted list of the filenames + :rtype: list(str) + :raises: Can raise errors from Ggit + """ + commit_id = Git.OId.new_from_string(commit) + commit_obj = repo.lookup(commit_id, Git.Commit) + tree = commit_obj.get_tree() + return sorted([tree.get(i).get_name() for i in range(0, tree.size())])
+ +
[docs]def delete_recipe(repo, branch, recipe_name): + """Delete a recipe from a branch. + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to delete + :type recipe_name: str + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit + """ + return delete_file(repo, branch, recipe_filename(recipe_name))
+ +
[docs]def delete_file(repo, branch, filename): + """Delete a file from a branch. + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: filename to delete + :type filename: str + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit + """ + parent_commit = head_commit(repo, branch) + parent_tree = parent_commit.get_tree() + builder = repo.create_tree_builder_from_tree(parent_tree) + builder.remove(filename) + (tree, sig, ref) = prepare_commit(repo, branch, builder) + message = "Recipe %s deleted" % filename + return repo.create_commit(ref, sig, sig, "UTF-8", message, tree, [parent_commit])
+ +
[docs]def revert_recipe(repo, branch, recipe_name, commit): + """Revert the contents of a recipe to that of a previous commit + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to revert + :type recipe_name: str + :param commit: Commit hash + :type commit: str + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit + """ + return revert_file(repo, branch, recipe_filename(recipe_name), commit)
+ +
[docs]def revert_file(repo, branch, filename, commit): + """Revert the contents of a file to that of a previous commit + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: filename to revert + :type filename: str + :param commit: Commit hash + :type commit: str + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit + """ + commit_id = Git.OId.new_from_string(commit) + commit_obj = repo.lookup(commit_id, Git.Commit) + revert_tree = commit_obj.get_tree() + entry = revert_tree.get_by_name(filename) + blob_id = entry.get_id() + parent_commit = head_commit(repo, branch) + + # Use treebuilder to modify the tree + parent_tree = parent_commit.get_tree() + builder = repo.create_tree_builder_from_tree(parent_tree) + builder.insert(filename, blob_id, Git.FileMode.BLOB) + (tree, sig, ref) = prepare_commit(repo, branch, builder) + commit_hash = commit_id.to_string() + message = "%s reverted to commit %s" % (filename, commit_hash) + return repo.create_commit(ref, sig, sig, "UTF-8", message, tree, [parent_commit])
+ +
[docs]def commit_recipe(repo, branch, recipe): + """Commit a recipe to a branch + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe: Recipe to commit + :type recipe: Recipe + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit + """ + try: + old_recipe = read_recipe_commit(repo, branch, recipe["name"]) + old_version = old_recipe["version"] + except Exception: + old_version = None + + recipe.bump_version(old_version) + recipe_toml = recipe.toml() + message = "Recipe %s, version %s saved." % (recipe["name"], recipe["version"]) + return write_commit(repo, branch, recipe.filename, message, recipe_toml)
+ +
[docs]def commit_recipe_file(repo, branch, filename): + """Commit a recipe file to a branch + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: Path to the recipe file to commit + :type filename: str + :returns: OId of the new commit + :rtype: Git.OId + :raises: Can raise errors from Ggit or RecipeFileError + """ + try: + recipe = recipe_from_file(filename) + except IOError: + raise RecipeFileError + + return commit_recipe(repo, branch, recipe)
+ +
[docs]def commit_recipe_directory(repo, branch, directory): + r"""Commit all \*.toml files from a directory, if they aren't already in git. + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param directory: The directory of \*.toml recipes to commit + :type directory: str + :returns: None + :raises: Can raise errors from Ggit or RecipeFileError + + Files with Toml or RecipeFileErrors will be skipped, and the remainder will + be tried. + """ + dir_files = set([e for e in os.listdir(directory) if e.endswith(".toml")]) + branch_files = set(list_branch_files(repo, branch)) + new_files = dir_files.difference(branch_files) + + for f in new_files: + # Skip files with errors, but try the others + try: + commit_recipe_file(repo, branch, joinpaths(directory, f)) + except (RecipeFileError, toml.TomlError): + pass
+ +
[docs]def tag_recipe_commit(repo, branch, recipe_name): + """Tag a file's most recent commit + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to tag + :type recipe_name: str + :returns: Tag id or None if it failed. + :rtype: Git.OId + :raises: Can raise errors from Ggit + + Uses tag_file_commit() + """ + if not repo_file_exists(repo, branch, recipe_filename(recipe_name)): + raise RecipeFileError("Unknown blueprint") + + return tag_file_commit(repo, branch, recipe_filename(recipe_name))
+ +
[docs]def tag_file_commit(repo, branch, filename): + """Tag a file's most recent commit + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: Filename to tag + :type filename: str + :returns: Tag id or None if it failed. + :rtype: Git.OId + :raises: Can raise errors from Ggit + + This uses git tags, of the form `refs/tags/<branch>/<filename>/r<revision>` + Only the most recent recipe commit can be tagged to prevent out of order tagging. + Revisions start at 1 and increment for each new commit that is tagged. + If the commit has already been tagged it will return false. + """ + file_commits = list_commits(repo, branch, filename) + if not file_commits: + return None + + # Find the most recently tagged version (may not be one) and add 1 to it. + for details in file_commits: + if details.revision is not None: + new_revision = details.revision + 1 + break + else: + new_revision = 1 + + name = "%s/%s/r%d" % (branch, filename, new_revision) + sig = Git.Signature.new_now("bdcs-api-server", "user-email") + commit_id = Git.OId.new_from_string(file_commits[0].commit) + commit = repo.lookup(commit_id, Git.Commit) + return repo.create_tag(name, commit, sig, name, Git.CreateFlags.NONE)
+ +
[docs]def find_commit_tag(repo, branch, filename, commit_id): + """Find the tag that matches the commit_id + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: filename to revert + :type filename: str + :param commit_id: The commit id to check + :type commit_id: Git.OId + :returns: The tag or None if there isn't one + :rtype: str or None + + There should be only 1 tag pointing to a commit, but there may not + be a tag at all. + + The tag will look like: 'refs/tags/<branch>/<filename>/r<revision>' + """ + pattern = "%s/%s/r*" % (branch, filename) + tags = [t for t in repo.list_tags_match(pattern) if is_commit_tag(repo, commit_id, t)] + if len(tags) != 1: + return None + else: + return tags[0]
+ +
[docs]def is_commit_tag(repo, commit_id, tag): + """Check to see if a tag points to a specific commit. + + :param repo: Open repository + :type repo: Git.Repository + :param commit_id: The commit id to check + :type commit_id: Git.OId + :param tag: The tag to check + :type tag: str + :returns: True if the tag points to the commit, False otherwise + :rtype: bool + """ + ref = repo.lookup_reference("refs/tags/" + tag) + tag_id = ref.get_target() + tag = repo.lookup(tag_id, Git.Tag) + target_id = tag.get_target_id() + return commit_id.compare(target_id) == 0
+ +
[docs]def get_revision_from_tag(tag): + """Return the revision number from a tag + + :param tag: The tag to exract the revision from + :type tag: str + :returns: The integer revision or None + :rtype: int or None + + The revision is the part after the r in 'branch/filename/rXXX' + """ + if tag is None: + return None + try: + return int(tag.rsplit('r', 2)[-1]) + except (ValueError, IndexError): + return None
+ +
[docs]class CommitDetails(DataHolder): + def __init__(self, commit, timestamp, message, revision=None): + DataHolder.__init__(self, + commit = commit, + timestamp = timestamp, + message = message, + revision = revision)
+ +
[docs]def list_commits(repo, branch, filename, limit=0): + """List the commit history of a file on a branch. + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: filename to revert + :type filename: str + :param limit: Number of commits to return (0=all) + :type limit: int + :returns: A list of commit details + :rtype: list(CommitDetails) + :raises: Can raise errors from Ggit + """ + revwalk = Git.RevisionWalker.new(repo) + branch_ref = "refs/heads/%s" % branch + revwalk.push_ref(branch_ref) + + commits = [] + while True: + commit_id = revwalk.next() + if not commit_id: + break + commit = repo.lookup(commit_id, Git.Commit) + + parents = commit.get_parents() + # No parents? Must be the first commit. + if parents.get_size() == 0: + continue + + tree = commit.get_tree() + # Is the filename in this tree? If not, move on. + if not tree.get_by_name(filename): + continue + + # Is filename different in all of the parent commits? + parent_commits = list(map(parents.get, range(0, parents.get_size()))) + is_diff = all([is_parent_diff(repo, filename, tree, pc) for pc in parent_commits]) + # No changes from parents, skip it. + if not is_diff: + continue + + tag = find_commit_tag(repo, branch, filename, commit.get_id()) + try: + commits.append(get_commit_details(commit, get_revision_from_tag(tag))) + if limit and len(commits) > limit: + break + except CommitTimeValError: + # Skip any commits that have trouble converting the time + # TODO - log details about this failure + pass + + # These will be in reverse time sort order thanks to revwalk + return commits
+ +
[docs]def get_commit_details(commit, revision=None): + """Return the details about a specific commit. + + :param commit: The commit to get details from + :type commit: Git.Commit + :param revision: Optional commit revision + :type revision: int + :returns: Details about the commit + :rtype: CommitDetails + :raises: CommitTimeValError or Ggit exceptions + + """ + message = commit.get_message() + commit_str = commit.get_id().to_string() + sig = commit.get_committer() + + datetime = sig.get_time() + # XXX What do we do with timezone? + _timezone = sig.get_time_zone() + timeval = GLib.TimeVal() + ok = datetime.to_timeval(timeval) + if not ok: + raise CommitTimeValError + time_str = timeval.to_iso8601() + + return CommitDetails(commit_str, time_str, message, revision)
+ +
[docs]def is_parent_diff(repo, filename, tree, parent): + """Check to see if the commit is different from its parents + + :param repo: Open repository + :type repo: Git.Repository + :param filename: filename to revert + :type filename: str + :param tree: The commit's tree + :type tree: Git.Tree + :param parent: The commit's parent commit + :type parent: Git.Commit + :retuns: True if filename in the commit is different from its parents + :rtype: bool + """ + diff_opts = Git.DiffOptions.new() + diff_opts.set_pathspec([filename]) + diff = Git.Diff.new_tree_to_tree(repo, parent.get_tree(), tree, diff_opts) + return diff.get_num_deltas() > 0
+ +
[docs]def find_name(name, lst): + """Find the dict matching the name in a list and return it. + + :param name: Name to search for + :type name: str + :param lst: List of dict's with "name" field + :returns: First dict with matching name, or None + :rtype: dict or None + """ + for e in lst: + if e["name"] == name: + return e + return None
+ +
[docs]def diff_items(title, old_items, new_items): + """Return the differences between two lists of dicts. + + :param title: Title of the entry + :type title: str + :param old_items: List of item dicts with "name" field + :type old_items: list(dict) + :param new_items: List of item dicts with "name" field + :type new_items: list(dict) + :returns: List of diff dicts with old/new entries + :rtype: list(dict) + """ + diffs = [] + old_names = set(m["name"] for m in old_items) + new_names = set(m["name"] for m in new_items) + + added_items = new_names.difference(old_names) + added_items = sorted(added_items, key=lambda n: n.lower()) + + removed_items = old_names.difference(new_names) + removed_items = sorted(removed_items, key=lambda n: n.lower()) + + same_items = old_names.intersection(new_names) + same_items = sorted(same_items, key=lambda n: n.lower()) + + for name in added_items: + diffs.append({"old":None, + "new":{title:find_name(name, new_items)}}) + + for name in removed_items: + diffs.append({"old":{title:find_name(name, old_items)}, + "new":None}) + + for name in same_items: + old_item = find_name(name, old_items) + new_item = find_name(name, new_items) + if old_item != new_item: + diffs.append({"old":{title:old_item}, + "new":{title:new_item}}) + + return diffs
+ + +
[docs]def recipe_diff(old_recipe, new_recipe): + """Diff two versions of a recipe + + :param old_recipe: The old version of the recipe + :type old_recipe: Recipe + :param new_recipe: The new version of the recipe + :type new_recipe: Recipe + :returns: A list of diff dict entries with old/new + :rtype: list(dict) + """ + + diffs = [] + # These cannot be added or removed, just different + for element in ["name", "description", "version"]: + if old_recipe[element] != new_recipe[element]: + diffs.append({"old":{element.title():old_recipe[element]}, + "new":{element.title():new_recipe[element]}}) + + diffs.extend(diff_items("Module", old_recipe["modules"], new_recipe["modules"])) + diffs.extend(diff_items("Package", old_recipe["packages"], new_recipe["packages"])) + diffs.extend(diff_items("Group", old_recipe["groups"], new_recipe["groups"])) + + return diffs
+ +
[docs]def repo_file_exists(repo, branch, filename): + """Return True if the filename exists on the branch + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param filename: Filename to check + :type filename: str + :returns: True if the filename exists on the HEAD of the branch, False otherwise. + :rtype: bool + """ + commit = head_commit(repo, branch).get_id().to_string() + commit_id = Git.OId.new_from_string(commit) + commit_obj = repo.lookup(commit_id, Git.Commit) + tree = commit_obj.get_tree() + return tree.get_by_name(filename) is not None
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/server.html b/f29-branch/_modules/pylorax/api/server.html new file mode 100644 index 00000000..cefdbd7c --- /dev/null +++ b/f29-branch/_modules/pylorax/api/server.html @@ -0,0 +1,299 @@ + + + + + + + + + + + pylorax.api.server — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.server

+#
+# Copyright (C) 2017  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("lorax-composer")
+
+from collections import namedtuple
+from flask import Flask, jsonify, redirect, send_from_directory
+from glob import glob
+import os
+
+from pylorax import vernum
+from pylorax.api.crossdomain import crossdomain
+from pylorax.api.v0 import v0_api
+from pylorax.sysutils import joinpaths
+
+GitLock = namedtuple("GitLock", ["repo", "lock", "dir"])
+
+server = Flask(__name__)
+
+__all__ = ["server", "GitLock"]
+
+@server.route('/')
+def server_root():
+    redirect("/api/docs/")
+
+@server.route("/api/docs/")
+@server.route("/api/docs/<path:path>")
+def api_docs(path=None):
+    # Find the html docs
+    try:
+        # This assumes it is running from the source tree
+        docs_path = os.path.abspath(joinpaths(os.path.dirname(__file__), "../../../docs/html"))
+    except IndexError:
+        docs_path = glob("/usr/share/doc/lorax-*/html/")[0]
+
+    if not path:
+        path="index.html"
+    return send_from_directory(docs_path, path)
+
+@server.route("/api/status")
+@crossdomain(origin="*")
+def v0_status():
+    """
+    `/api/v0/status`
+    ^^^^^^^^^^^^^^^^
+    Return the status of the API Server::
+
+          { "api": "0",
+            "build": "devel",
+            "db_supported": true,
+            "db_version": "0",
+            "schema_version": "0",
+            "backend": "lorax-composer",
+            "msgs": []}
+
+    The 'msgs' field can be a list of strings describing startup problems or status that
+    should be displayed to the user. eg. if the compose templates are not depsolving properly
+    the errors will be in 'msgs'.
+    """
+    return jsonify(backend="lorax-composer",
+                   build=vernum,
+                   api="0",
+                   db_version="0",
+                   schema_version="0",
+                   db_supported=True,
+                   msgs=server.config["TEMPLATE_ERRORS"])
+
+v0_api(server)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/timestamp.html b/f29-branch/_modules/pylorax/api/timestamp.html new file mode 100644 index 00000000..d8cf1a45 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/timestamp.html @@ -0,0 +1,268 @@ + + + + + + + + + + + pylorax.api.timestamp — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.timestamp

+#
+# Copyright (C) 2018  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, see <http://www.gnu.org/licenses/>.
+#
+
+import pytoml as toml
+import time
+
+from pylorax.sysutils import joinpaths
+
+TS_CREATED  = "created"
+TS_STARTED  = "started"
+TS_FINISHED = "finished"
+
+
[docs]def write_timestamp(destdir, ty): + path = joinpaths(destdir, "times.toml") + + try: + contents = toml.loads(open(path, "r").read()) + except IOError: + contents = toml.loads("") + + if ty == TS_CREATED: + contents[TS_CREATED] = time.time() + elif ty == TS_STARTED: + contents[TS_STARTED] = time.time() + elif ty == TS_FINISHED: + contents[TS_FINISHED] = time.time() + + with open(path, "w") as f: + f.write(toml.dumps(contents))
+ +
[docs]def timestamp_dict(destdir): + path = joinpaths(destdir, "times.toml") + + try: + return toml.loads(open(path, "r").read()) + except IOError: + return toml.loads("")
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/v0.html b/f29-branch/_modules/pylorax/api/v0.html new file mode 100644 index 00000000..fe7a25cb --- /dev/null +++ b/f29-branch/_modules/pylorax/api/v0.html @@ -0,0 +1,2303 @@ + + + + + + + + + + + pylorax.api.v0 — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.v0

+#
+# Copyright (C) 2017-2018  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, see <http://www.gnu.org/licenses/>.
+#
+""" Setup v0 of the API server
+
+v0_api() must be called to setup the API routes for Flask
+
+Status Responses
+----------------
+
+Some requests only return a status/error response.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+  Example response::
+
+      {
+        "status": true
+      }
+
+  Error response::
+
+      {
+        "errors": ["ggit-error: Failed to remove entry. File isn't in the tree - jboss.toml (-1)"]
+        "status": false
+      }
+
+API Routes
+----------
+
+All of the blueprints routes support the optional `branch` argument. If it is not
+used then the API will use the `master` branch for blueprints. If you want to create
+a new branch use the `new` or `workspace` routes with ?branch=<branch-name> to
+store the new blueprint on the new branch.
+
+`/api/v0/blueprints/list`
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  List the available blueprints::
+
+      { "limit": 20,
+        "offset": 0,
+        "blueprints": [
+          "atlas",
+          "development",
+          "glusterfs",
+          "http-server",
+          "jboss",
+          "kubernetes" ],
+        "total": 6 }
+
+`/api/v0/blueprints/info/<blueprint_names>[?format=<json|toml>]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the JSON representation of the blueprint. This includes 3 top level
+  objects.  `changes` which lists whether or not the workspace is different from
+  the most recent commit. `blueprints` which lists the JSON representation of the
+  blueprint, and `errors` which will list any errors, like non-existant blueprints.
+
+  By default the response is JSON, but if `?format=toml` is included in the URL's
+  arguments it will return the response as the blueprint's raw TOML content.
+  *Unless* there is an error which will only return a 400 and a standard error
+  `Status Response`_.
+
+  If there is an error when JSON is requested the successful blueprints and the
+  errors will both be returned.
+
+  Example of json response::
+
+      {
+        "changes": [
+          {
+            "changed": false,
+            "name": "glusterfs"
+          }
+        ],
+        "errors": [],
+        "blueprints": [
+          {
+            "description": "An example GlusterFS server with samba",
+            "modules": [
+              {
+                "name": "glusterfs",
+                "version": "3.7.*"
+              },
+              {
+                "name": "glusterfs-cli",
+                "version": "3.7.*"
+              }
+            ],
+            "name": "glusterfs",
+            "packages": [
+              {
+                "name": "2ping",
+                "version": "3.2.1"
+              },
+              {
+                "name": "samba",
+                "version": "4.2.*"
+              }
+            ],
+            "version": "0.0.6"
+          }
+        ]
+      }
+
+  Error example::
+
+      {
+        "changes": [],
+        "errors": ["ggit-error: the path 'missing.toml' does not exist in the given tree (-3)"]
+        "blueprints": []
+      }
+
+`/api/v0/blueprints/changes/<blueprint_names>[?offset=0&limit=20]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the commits to a blueprint. By default it returns the first 20 commits, this
+  can be changed by passing `offset` and/or `limit`. The response will include the
+  commit hash, summary, timestamp, and optionally the revision number. The commit
+  hash can be passed to `/api/v0/blueprints/diff/` to retrieve the exact changes.
+
+  Example::
+
+      {
+        "errors": [],
+        "limit": 20,
+        "offset": 0,
+        "blueprints": [
+          {
+            "changes": [
+              {
+                "commit": "e083921a7ed1cf2eec91ad12b9ad1e70ef3470be",
+                "message": "blueprint glusterfs, version 0.0.6 saved.",
+                "revision": null,
+                "timestamp": "2017-11-23T00:18:13Z"
+              },
+              {
+                "commit": "cee5f4c20fc33ea4d54bfecf56f4ad41ad15f4f3",
+                "message": "blueprint glusterfs, version 0.0.5 saved.",
+                "revision": null,
+                "timestamp": "2017-11-11T01:00:28Z"
+              },
+              {
+                "commit": "29b492f26ed35d80800b536623bafc51e2f0eff2",
+                "message": "blueprint glusterfs, version 0.0.4 saved.",
+                "revision": null,
+                "timestamp": "2017-11-11T00:28:30Z"
+              },
+              {
+                "commit": "03374adbf080fe34f5c6c29f2e49cc2b86958bf2",
+                "message": "blueprint glusterfs, version 0.0.3 saved.",
+                "revision": null,
+                "timestamp": "2017-11-10T23:15:52Z"
+              },
+              {
+                "commit": "0e08ecbb708675bfabc82952599a1712a843779d",
+                "message": "blueprint glusterfs, version 0.0.2 saved.",
+                "revision": null,
+                "timestamp": "2017-11-10T23:14:56Z"
+              },
+              {
+                "commit": "3e11eb87a63d289662cba4b1804a0947a6843379",
+                "message": "blueprint glusterfs, version 0.0.1 saved.",
+                "revision": null,
+                "timestamp": "2017-11-08T00:02:47Z"
+              }
+            ],
+            "name": "glusterfs",
+            "total": 6
+          }
+        ]
+      }
+
+POST `/api/v0/blueprints/new`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Create a new blueprint, or update an existing blueprint. This supports both JSON and TOML
+  for the blueprint format. The blueprint should be in the body of the request with the
+  `Content-Type` header set to either `application/json` or `text/x-toml`.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+DELETE `/api/v0/blueprints/delete/<blueprint_name>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Delete a blueprint. The blueprint is deleted from the branch, and will no longer
+  be listed by the `list` route. A blueprint can be undeleted using the `undo` route
+  to revert to a previous commit. This will also delete the workspace copy of the
+  blueprint.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+POST `/api/v0/blueprints/workspace`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Write a blueprint to the temporary workspace. This works exactly the same as `new` except
+  that it does not create a commit. JSON and TOML bodies are supported.
+
+  The workspace is meant to be used as a temporary blueprint storage for clients.
+  It will be read by the `info` and `diff` routes if it is different from the
+  most recent commit.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+DELETE `/api/v0/blueprints/workspace/<blueprint_name>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Remove the temporary workspace copy of a blueprint. The `info` route will now
+  return the most recent commit of the blueprint. Any changes that were in the
+  workspace will be lost.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+POST `/api/v0/blueprints/undo/<blueprint_name>/<commit>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  This will revert the blueprint to a previous commit. The commit hash from the `changes`
+  route can be used in this request.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+POST `/api/v0/blueprints/tag/<blueprint_name>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Tag a blueprint as a new release. This uses git tags with a special format.
+  `refs/tags/<branch>/<filename>/r<revision>`. Only the most recent blueprint commit
+  can be tagged. Revisions start at 1 and increment for each new tag
+  (per-blueprint). If the commit has already been tagged it will return false.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+`/api/v0/blueprints/diff/<blueprint_name>/<from_commit>/<to_commit>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the differences between two commits, or the workspace. The commit hash
+  from the `changes` response can be used here, or several special strings:
+
+  - NEWEST will select the newest git commit. This works for `from_commit` or `to_commit`
+  - WORKSPACE will select the workspace copy. This can only be used in `to_commit`
+
+  eg. `/api/v0/blueprints/diff/glusterfs/NEWEST/WORKSPACE` will return the differences
+  between the most recent git commit and the contents of the workspace.
+
+  Each entry in the response's diff object contains the old blueprint value and the new one.
+  If old is null and new is set, then it was added.
+  If new is null and old is set, then it was removed.
+  If both are set, then it was changed.
+
+  The old/new entries will have the name of the blueprint field that was changed. This
+  can be one of: Name, Description, Version, Module, or Package.
+  The contents for these will be the old/new values for them.
+
+  In the example below the version was changed and the ping package was added.
+
+  Example::
+
+      {
+        "diff": [
+          {
+            "new": {
+              "Version": "0.0.6"
+            },
+            "old": {
+              "Version": "0.0.5"
+            }
+          },
+          {
+            "new": {
+              "Package": {
+                "name": "ping",
+                "version": "3.2.1"
+              }
+            },
+            "old": null
+          }
+        ]
+      }
+
+`/api/v0/blueprints/freeze/<blueprint_names>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return a JSON representation of the blueprint with the package and module versions set
+  to the exact versions chosen by depsolving the blueprint.
+
+  Example::
+
+      {
+        "errors": [],
+        "blueprints": [
+          {
+            "blueprint": {
+              "description": "An example GlusterFS server with samba",
+              "modules": [
+                {
+                  "name": "glusterfs",
+                  "version": "3.8.4-18.4.el7.x86_64"
+                },
+                {
+                  "name": "glusterfs-cli",
+                  "version": "3.8.4-18.4.el7.x86_64"
+                }
+              ],
+              "name": "glusterfs",
+              "packages": [
+                {
+                  "name": "ping",
+                  "version": "2:3.2.1-2.el7.noarch"
+                },
+                {
+                  "name": "samba",
+                  "version": "4.6.2-8.el7.x86_64"
+                }
+              ],
+              "version": "0.0.6"
+            }
+          }
+        ]
+      }
+
+`/api/v0/blueprints/depsolve/<blueprint_names>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Depsolve the blueprint using yum, return the blueprint used, and the NEVRAs of the packages
+  chosen to satisfy the blueprint's requirements. The response will include a list of results,
+  with the full dependency list in `dependencies`, the NEVRAs for the blueprint's direct modules
+  and packages in `modules`, and any error will be in `errors`.
+
+  Example::
+
+      {
+        "errors": [],
+        "blueprints": [
+          {
+            "dependencies": [
+              {
+                "arch": "noarch",
+                "epoch": "0",
+                "name": "2ping",
+                "release": "2.el7",
+                "version": "3.2.1"
+              },
+              {
+                "arch": "x86_64",
+                "epoch": "0",
+                "name": "acl",
+                "release": "12.el7",
+                "version": "2.2.51"
+              },
+              {
+                "arch": "x86_64",
+                "epoch": "0",
+                "name": "audit-libs",
+                "release": "3.el7",
+                "version": "2.7.6"
+              },
+              {
+                "arch": "x86_64",
+                "epoch": "0",
+                "name": "avahi-libs",
+                "release": "17.el7",
+                "version": "0.6.31"
+              },
+              ...
+            ],
+            "modules": [
+              {
+                "arch": "noarch",
+                "epoch": "0",
+                "name": "2ping",
+                "release": "2.el7",
+                "version": "3.2.1"
+              },
+              {
+                "arch": "x86_64",
+                "epoch": "0",
+                "name": "glusterfs",
+                "release": "18.4.el7",
+                "version": "3.8.4"
+              },
+              ...
+            ],
+            "blueprint": {
+              "description": "An example GlusterFS server with samba",
+              "modules": [
+                {
+                  "name": "glusterfs",
+                  "version": "3.7.*"
+                },
+             ...
+            }
+          }
+        ]
+      }
+
+`/api/v0/projects/list[?offset=0&limit=20]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  List all of the available projects. By default this returns the first 20 items,
+  but this can be changed by setting the `offset` and `limit` arguments.
+
+  Example::
+
+      {
+        "limit": 20,
+        "offset": 0,
+        "projects": [
+          {
+            "description": "0 A.D. (pronounced \"zero ey-dee\") is a ...",
+            "homepage": "http://play0ad.com",
+            "name": "0ad",
+            "summary": "Cross-Platform RTS Game of Ancient Warfare",
+            "upstream_vcs": "UPSTREAM_VCS"
+          },
+          ...
+        ],
+        "total": 21770
+      }
+
+`/api/v0/projects/info/<project_names>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return information about the comma-separated list of projects. It includes the description
+  of the package along with the list of available builds.
+
+  Example::
+
+      {
+        "projects": [
+          {
+            "builds": [
+              {
+                "arch": "x86_64",
+                "build_config_ref": "BUILD_CONFIG_REF",
+                "build_env_ref": "BUILD_ENV_REF",
+                "build_time": "2017-03-01T08:39:23",
+                "changelog": "- restore incremental backups correctly, files ...",
+                "epoch": "2",
+                "metadata": {},
+                "release": "32.el7",
+                "source": {
+                  "license": "GPLv3+",
+                  "metadata": {},
+                  "source_ref": "SOURCE_REF",
+                  "version": "1.26"
+                }
+              }
+            ],
+            "description": "The GNU tar program saves many ...",
+            "homepage": "http://www.gnu.org/software/tar/",
+            "name": "tar",
+            "summary": "A GNU file archiving program",
+            "upstream_vcs": "UPSTREAM_VCS"
+          }
+        ]
+      }
+
+`/api/v0/projects/depsolve/<project_names>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Depsolve the comma-separated list of projects and return the list of NEVRAs needed
+  to satisfy the request.
+
+  Example::
+
+      {
+        "projects": [
+          {
+            "arch": "noarch",
+            "epoch": "0",
+            "name": "basesystem",
+            "release": "7.el7",
+            "version": "10.0"
+          },
+          {
+            "arch": "x86_64",
+            "epoch": "0",
+            "name": "bash",
+            "release": "28.el7",
+            "version": "4.2.46"
+          },
+          {
+            "arch": "x86_64",
+            "epoch": "0",
+            "name": "filesystem",
+            "release": "21.el7",
+            "version": "3.2"
+          },
+          ...
+        ]
+      }
+
+`/api/v0/projects/source/list`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the list of repositories used for depsolving and installing packages.
+
+  Example::
+
+      {
+        "sources": [
+          "fedora",
+          "fedora-cisco-openh264",
+          "fedora-updates-testing",
+          "fedora-updates"
+        ]
+      }
+
+`/api/v0/projects/source/info/<source-names>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return information about the comma-separated list of source names. Or all of the
+  sources if '*' is passed. Note that general globbing is not supported, only '*'.
+
+  immutable system sources will have the "system" field set to true. User added sources
+  will have it set to false. System sources cannot be changed or deleted.
+
+  Example::
+
+      {
+        "errors": [],
+        "sources": {
+          "fedora": {
+            "check_gpg": true,
+            "check_ssl": true,
+            "gpgkey_urls": [
+              "file:///etc/pki/rpm-gpg/RPM-GPG-KEY-fedora-28-x86_64"
+            ],
+            "name": "fedora",
+            "proxy": "http://proxy.brianlane.com:8123",
+            "system": true,
+            "type": "yum-metalink",
+            "url": "https://mirrors.fedoraproject.org/metalink?repo=fedora-28&arch=x86_64"
+          }
+        }
+      }
+
+POST `/api/v0/projects/source/new`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Add (or change) a source for use when depsolving blueprints and composing images.
+
+  The ``proxy`` and ``gpgkey_urls`` entries are optional. All of the others are required. The supported
+  types for the urls are:
+
+  * ``yum-baseurl`` is a URL to a yum repository.
+  * ``yum-mirrorlist`` is a URL for a mirrorlist.
+  * ``yum-metalink`` is a URL for a metalink.
+
+  If ``check_ssl`` is true the https certificates must be valid. If they are self-signed you can either set
+  this to false, or add your Certificate Authority to the host system.
+
+  If ``check_gpg`` is true the GPG key must either be installed on the host system, or ``gpgkey_urls``
+  should point to it.
+
+  You can edit an existing source (other than system sources), by doing a POST
+  of the new version of the source. It will overwrite the previous one.
+
+  Example::
+
+      {
+          "name": "custom-source-1",
+          "url": "https://url/path/to/repository/",
+          "type": "yum-baseurl",
+          "check_ssl": true,
+          "check_gpg": true,
+          "gpgkey_urls": [
+              "https://url/path/to/gpg-key"
+          ]
+      }
+
+DELETE `/api/v0/projects/source/delete/<source-name>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Delete a user added source. This will fail if a system source is passed to
+  it.
+
+  The response will be a status response with `status` set to true, or an
+  error response with it set to false and an error message included.
+
+`/api/v0/modules/list[?offset=0&limit=20]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return a list of all of the available modules. This includes the name and the
+  group_type, which is always "rpm" for lorax-composer. By default this returns
+  the first 20 items. This can be changed by setting the `offset` and `limit`
+  arguments.
+
+  Example::
+
+      {
+        "limit": 20,
+        "modules": [
+          {
+            "group_type": "rpm",
+            "name": "0ad"
+          },
+          {
+            "group_type": "rpm",
+            "name": "0ad-data"
+          },
+          {
+            "group_type": "rpm",
+            "name": "0install"
+          },
+          {
+            "group_type": "rpm",
+            "name": "2048-cli"
+          },
+          ...
+        ]
+        "total": 21770
+      }
+
+`/api/v0/modules/list/<module_names>[?offset=0&limit=20]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the list of comma-separated modules. Output is the same as `/modules/list`
+
+  Example::
+
+      {
+        "limit": 20,
+        "modules": [
+          {
+            "group_type": "rpm",
+            "name": "tar"
+          }
+        ],
+        "offset": 0,
+        "total": 1
+      }
+
+`/api/v0/modules/info/<module_names>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the module's dependencies, and the information about the module.
+
+  Example::
+
+      {
+        "modules": [
+          {
+            "dependencies": [
+              {
+                "arch": "noarch",
+                "epoch": "0",
+                "name": "basesystem",
+                "release": "7.el7",
+                "version": "10.0"
+              },
+              {
+                "arch": "x86_64",
+                "epoch": "0",
+                "name": "bash",
+                "release": "28.el7",
+                "version": "4.2.46"
+              },
+              ...
+            ],
+            "description": "The GNU tar program saves ...",
+            "homepage": "http://www.gnu.org/software/tar/",
+            "name": "tar",
+            "summary": "A GNU file archiving program",
+            "upstream_vcs": "UPSTREAM_VCS"
+          }
+        ]
+      }
+
+POST `/api/v0/compose`
+^^^^^^^^^^^^^^^^^^^^^^
+
+  Start a compose. The content type should be 'application/json' and the body of the POST
+  should look like this
+  
+  Example::
+
+      {
+        "blueprint_name": "http-server",
+        "compose_type": "tar",
+        "branch": "master"
+      }
+
+  Pass it the name of the blueprint, the type of output (from '/api/v0/compose/types'), and the
+  blueprint branch to use. 'branch' is optional and will default to master. It will create a new
+  build and add it to the queue. It returns the build uuid and a status if it succeeds
+
+  Example::
+  
+      {
+        "build_id": "e6fa6db4-9c81-4b70-870f-a697ca405cdf",
+        "status": true
+      }
+
+`/api/v0/compose/types`
+^^^^^^^^^^^^^^^^^^^^^^^
+
+  Returns the list of supported output types that are valid for use with 'POST /api/v0/compose'
+
+  Example::
+
+      {
+        "types": [
+          {
+            "enabled": true,
+            "name": "tar"
+          }
+        ]
+      }
+
+`/api/v0/compose/queue`
+^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the status of the build queue. It includes information about the builds waiting,
+  and the build that is running.
+
+  Example::
+
+      {
+        "new": [
+          {
+            "id": "45502a6d-06e8-48a5-a215-2b4174b3614b",
+            "blueprint": "glusterfs",
+            "queue_status": "WAITING",
+            "job_created": 1517362647.4570868,
+            "version": "0.0.6"
+          },
+          {
+            "id": "6d292bd0-bec7-4825-8d7d-41ef9c3e4b73",
+            "blueprint": "kubernetes",
+            "queue_status": "WAITING",
+            "job_created": 1517362659.0034983,
+            "version": "0.0.1"
+          }
+        ],
+        "run": [
+          {
+            "id": "745712b2-96db-44c0-8014-fe925c35e795",
+            "blueprint": "glusterfs",
+            "queue_status": "RUNNING",
+            "job_created": 1517362633.7965999,
+            "job_started": 1517362633.8001345,
+            "version": "0.0.6"
+          }
+        ]
+      }
+
+`/api/v0/compose/finished`
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the details on all of the finished composes on the system.
+
+  Example::
+
+      {
+        "finished": [
+          {
+            "id": "70b84195-9817-4b8a-af92-45e380f39894",
+            "blueprint": "glusterfs",
+            "queue_status": "FINISHED",
+            "job_created": 1517351003.8210032,
+            "job_started": 1517351003.8230415,
+            "job_finished": 1517359234.1003145,
+            "version": "0.0.6"
+          },
+          {
+            "id": "e695affd-397f-4af9-9022-add2636e7459",
+            "blueprint": "glusterfs",
+            "queue_status": "FINISHED",
+            "job_created": 1517362289.7193348,
+            "job_started": 1517362289.9751132,
+            "job_finished": 1517363500.1234567,
+            "version": "0.0.6"
+          }
+        ]
+      }
+
+`/api/v0/compose/failed`
+^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the details on all of the failed composes on the system.
+
+  Example::
+
+      {
+        "failed": [
+           {
+            "id": "8c8435ef-d6bd-4c68-9bf1-a2ef832e6b1a",
+            "blueprint": "http-server",
+            "queue_status": "FAILED",
+            "job_created": 1517523249.9301329,
+            "job_started": 1517523249.9314211,
+            "job_finished": 1517523255.5623411,
+            "version": "0.0.2"
+          }
+        ]
+      }
+
+`/api/v0/compose/status/<uuids>[?blueprint=<blueprint_name>&status=<compose_status>&type=<compose_type>]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Return the details for each of the comma-separated list of uuids. A uuid of '*' will return
+  details for all composes.
+
+  Example::
+
+      {
+        "uuids": [
+          {
+            "id": "8c8435ef-d6bd-4c68-9bf1-a2ef832e6b1a",
+            "blueprint": "http-server",
+            "queue_status": "FINISHED",
+            "job_created": 1517523644.2384307,
+            "job_started": 1517523644.2551234,
+            "job_finished": 1517523689.9864314,
+            "version": "0.0.2"
+          },
+          {
+            "id": "45502a6d-06e8-48a5-a215-2b4174b3614b",
+            "blueprint": "glusterfs",
+            "queue_status": "FINISHED",
+            "job_created": 1517363442.188399,
+            "job_started": 1517363442.325324,
+            "job_finished": 1517363451.653621,
+            "version": "0.0.6"
+          }
+        ]
+      }
+
+DELETE `/api/v0/compose/cancel/<uuid>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Cancel the build, if it is not finished, and delete the results. It will return a
+  status of True if it is successful.
+
+  Example::
+
+      {
+        "status": true,
+        "uuid": "03397f8d-acff-4cdb-bd31-f629b7a948f5"
+      }
+
+DELETE `/api/v0/compose/delete/<uuids>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Delete the list of comma-separated uuids from the compose results.
+
+  Example::
+
+      {
+        "errors": [],
+        "uuids": [
+          {
+            "status": true,
+            "uuid": "ae1bf7e3-7f16-4c9f-b36e-3726a1093fd0"
+          }
+        ]
+      }
+
+`/api/v0/compose/info/<uuid>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Get detailed information about the compose. The returned JSON string will
+  contain the following information:
+
+    * id - The uuid of the comoposition
+    * config - containing the configuration settings used to run Anaconda
+    * blueprint - The depsolved blueprint used to generate the kickstart
+    * commit - The (local) git commit hash for the blueprint used
+    * deps - The NEVRA of all of the dependencies used in the composition
+    * compose_type - The type of output generated (tar, iso, etc.)
+    * queue_status - The final status of the composition (FINISHED or FAILED)
+
+  Example::
+
+      {
+        "commit": "7078e521a54b12eae31c3fd028680da7a0815a4d",
+        "compose_type": "tar",
+        "config": {
+          "anaconda_args": "",
+          "armplatform": "",
+          "compress_args": [],
+          "compression": "xz",
+          "image_name": "root.tar.xz",
+          ...
+        },
+        "deps": {
+          "packages": [
+            {
+              "arch": "x86_64",
+              "epoch": "0",
+              "name": "acl",
+              "release": "14.el7",
+              "version": "2.2.51"
+            }
+          ]
+        },
+        "id": "c30b7d80-523b-4a23-ad52-61b799739ce8",
+        "queue_status": "FINISHED",
+        "blueprint": {
+          "description": "An example kubernetes master",
+          ...
+        }
+      }
+
+`/api/v0/compose/metadata/<uuid>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Returns a .tar of the metadata used for the build. This includes all the
+  information needed to reproduce the build, including the final kickstart
+  populated with repository and package NEVRA.
+
+  The mime type is set to 'application/x-tar' and the filename is set to
+  UUID-metadata.tar
+
+  The .tar is uncompressed, but is not large.
+
+`/api/v0/compose/results/<uuid>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Returns a .tar of the metadata, logs, and output image of the build. This
+  includes all the information needed to reproduce the build, including the
+  final kickstart populated with repository and package NEVRA. The output image
+  is already in compressed form so the returned tar is not compressed.
+
+  The mime type is set to 'application/x-tar' and the filename is set to
+  UUID.tar
+
+`/api/v0/compose/logs/<uuid>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Returns a .tar of the anaconda build logs. The tar is not compressed, but is
+  not large.
+
+  The mime type is set to 'application/x-tar' and the filename is set to
+  UUID-logs.tar
+
+`/api/v0/compose/image/<uuid>`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Returns the output image from the build. The filename is set to the filename
+  from the build with the UUID as a prefix. eg. UUID-root.tar.xz or UUID-boot.iso.
+
+`/api/v0/compose/log/<uuid>[?size=kbytes]`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+  Returns the end of the anaconda.log. The size parameter is optional and defaults to 1Mbytes
+  if it is not included. The returned data is raw text from the end of the logfile, starting on
+  a line boundry.
+
+  Example::
+
+      12:59:24,222 INFO anaconda: Running Thread: AnaConfigurationThread (140629395244800)
+      12:59:24,223 INFO anaconda: Configuring installed system
+      12:59:24,912 INFO anaconda: Configuring installed system
+      12:59:24,912 INFO anaconda: Creating users
+      12:59:24,913 INFO anaconda: Clearing libuser.conf at /tmp/libuser.Dyy8Gj
+      12:59:25,154 INFO anaconda: Creating users
+      12:59:25,155 INFO anaconda: Configuring addons
+      12:59:25,155 INFO anaconda: Configuring addons
+      12:59:25,155 INFO anaconda: Generating initramfs
+      12:59:49,467 INFO anaconda: Generating initramfs
+      12:59:49,467 INFO anaconda: Running post-installation scripts
+      12:59:49,467 INFO anaconda: Running kickstart %%post script(s)
+      12:59:50,782 INFO anaconda: All kickstart %%post script(s) have been run
+      12:59:50,782 INFO anaconda: Running post-installation scripts
+      12:59:50,784 INFO anaconda: Thread Done: AnaConfigurationThread (140629395244800)
+
+"""
+
+import logging
+log = logging.getLogger("lorax-composer")
+
+import os
+from flask import jsonify, request, Response, send_file
+import pytoml as toml
+
+from pylorax.sysutils import joinpaths
+from pylorax.api.checkparams import checkparams
+from pylorax.api.compose import start_build, compose_types
+from pylorax.api.crossdomain import crossdomain
+from pylorax.api.errors import *                               # pylint: disable=wildcard-import
+from pylorax.api.projects import projects_list, projects_info, projects_depsolve
+from pylorax.api.projects import modules_list, modules_info, ProjectsError, repo_to_source
+from pylorax.api.projects import get_repo_sources, delete_repo_source, source_to_repo, dnf_repo_to_file_repo
+from pylorax.api.queue import queue_status, build_status, uuid_delete, uuid_status, uuid_info
+from pylorax.api.queue import uuid_tar, uuid_image, uuid_cancel, uuid_log
+from pylorax.api.recipes import RecipeError, list_branch_files, read_recipe_commit, recipe_filename, list_commits
+from pylorax.api.recipes import recipe_from_dict, recipe_from_toml, commit_recipe, delete_recipe, revert_recipe
+from pylorax.api.recipes import tag_recipe_commit, recipe_diff, RecipeFileError
+from pylorax.api.regexes import VALID_API_STRING
+from pylorax.api.workspace import workspace_read, workspace_write, workspace_delete
+
+# The API functions don't actually get called by any code here
+# pylint: disable=unused-variable
+
+
[docs]def take_limits(iterable, offset, limit): + """ Apply offset and limit to an iterable object + + :param iterable: The object to limit + :type iterable: iter + :param offset: The number of items to skip + :type offset: int + :param limit: The total number of items to return + :type limit: int + :returns: A subset of the iterable + """ + return iterable[offset:][:limit]
+ +
[docs]def blueprint_exists(api, branch, blueprint_name): + """Return True if the blueprint exists + + :param api: flask object + :type api: Flask + :param branch: Branch name + :type branch: str + :param recipe_name: Recipe name to read + :type recipe_name: str + """ + try: + with api.config["GITLOCK"].lock: + read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + + return True + except (RecipeError, RecipeFileError): + return False
+ +
[docs]def v0_api(api): + # Note that Sphinx will not generate documentations for any of these. + @api.route("/api/v0/blueprints/list") + @crossdomain(origin="*") + def v0_blueprints_list(): + """List the available blueprints on a branch.""" + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + limit = int(request.args.get("limit", "20")) + offset = int(request.args.get("offset", "0")) + except ValueError as e: + return jsonify(status=False, errors=[{"id": BAD_LIMIT_OR_OFFSET, "msg": str(e)}]), 400 + + with api.config["GITLOCK"].lock: + blueprints = [f[:-5] for f in list_branch_files(api.config["GITLOCK"].repo, branch)] + limited_blueprints = take_limits(blueprints, offset, limit) + return jsonify(blueprints=limited_blueprints, limit=limit, offset=offset, total=len(blueprints)) + + @api.route("/api/v0/blueprints/info", defaults={'blueprint_names': ""}) + @api.route("/api/v0/blueprints/info/<blueprint_names>") + @crossdomain(origin="*") + @checkparams([("blueprint_names", "", "no blueprint names given")]) + def v0_blueprints_info(blueprint_names): + """Return the contents of the blueprint, or a list of blueprints""" + if VALID_API_STRING.match(blueprint_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + out_fmt = request.args.get("format", "json") + if VALID_API_STRING.match(out_fmt) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in format argument"}]), 400 + + blueprints = [] + changes = [] + errors = [] + for blueprint_name in [n.strip() for n in blueprint_names.split(",")]: + exceptions = [] + # Get the workspace version (if it exists) + try: + with api.config["GITLOCK"].lock: + ws_blueprint = workspace_read(api.config["GITLOCK"].repo, branch, blueprint_name) + except Exception as e: + ws_blueprint = None + exceptions.append(str(e)) + log.error("(v0_blueprints_info) %s", str(e)) + + # Get the git version (if it exists) + try: + with api.config["GITLOCK"].lock: + git_blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + except RecipeFileError as e: + # Adding an exception would be redundant, skip it + git_blueprint = None + log.error("(v0_blueprints_info) %s", str(e)) + except Exception as e: + git_blueprint = None + exceptions.append(str(e)) + log.error("(v0_blueprints_info) %s", str(e)) + + if not ws_blueprint and not git_blueprint: + # Neither blueprint, return an error + errors.append({"id": UNKNOWN_BLUEPRINT, "msg": "%s: %s" % (blueprint_name, ", ".join(exceptions))}) + elif ws_blueprint and not git_blueprint: + # No git blueprint, return the workspace blueprint + changes.append({"name":blueprint_name, "changed":True}) + blueprints.append(ws_blueprint) + elif not ws_blueprint and git_blueprint: + # No workspace blueprint, no change, return the git blueprint + changes.append({"name":blueprint_name, "changed":False}) + blueprints.append(git_blueprint) + else: + # Both exist, maybe changed, return the workspace blueprint + changes.append({"name":blueprint_name, "changed":ws_blueprint != git_blueprint}) + blueprints.append(ws_blueprint) + + # Sort all the results by case-insensitive blueprint name + changes = sorted(changes, key=lambda c: c["name"].lower()) + blueprints = sorted(blueprints, key=lambda r: r["name"].lower()) + + if out_fmt == "toml": + if errors: + # If there are errors they need to be reported, use JSON and 400 for this + return jsonify(status=False, errors=errors), 400 + else: + # With TOML output we just want to dump the raw blueprint, skipping the rest. + return "\n\n".join([r.toml() for r in blueprints]) + else: + return jsonify(changes=changes, blueprints=blueprints, errors=errors) + + @api.route("/api/v0/blueprints/changes", defaults={'blueprint_names': ""}) + @api.route("/api/v0/blueprints/changes/<blueprint_names>") + @crossdomain(origin="*") + @checkparams([("blueprint_names", "", "no blueprint names given")]) + def v0_blueprints_changes(blueprint_names): + """Return the changes to a blueprint or list of blueprints""" + if VALID_API_STRING.match(blueprint_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + limit = int(request.args.get("limit", "20")) + offset = int(request.args.get("offset", "0")) + except ValueError as e: + return jsonify(status=False, errors=[{"id": BAD_LIMIT_OR_OFFSET, "msg": str(e)}]), 400 + + blueprints = [] + errors = [] + for blueprint_name in [n.strip() for n in blueprint_names.split(",")]: + filename = recipe_filename(blueprint_name) + try: + with api.config["GITLOCK"].lock: + commits = list_commits(api.config["GITLOCK"].repo, branch, filename) + except Exception as e: + errors.append({"id": BLUEPRINTS_ERROR, "msg": "%s: %s" % (blueprint_name, str(e))}) + log.error("(v0_blueprints_changes) %s", str(e)) + else: + if commits: + limited_commits = take_limits(commits, offset, limit) + blueprints.append({"name":blueprint_name, "changes":limited_commits, "total":len(commits)}) + else: + # no commits means there is no blueprint in the branch + errors.append({"id": UNKNOWN_BLUEPRINT, "msg": "%s" % blueprint_name}) + + blueprints = sorted(blueprints, key=lambda r: r["name"].lower()) + + return jsonify(blueprints=blueprints, errors=errors, offset=offset, limit=limit) + + @api.route("/api/v0/blueprints/new", methods=["POST"]) + @crossdomain(origin="*") + def v0_blueprints_new(): + """Commit a new blueprint""" + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + if request.headers['Content-Type'] == "text/x-toml": + blueprint = recipe_from_toml(request.data) + else: + blueprint = recipe_from_dict(request.get_json(cache=False)) + + if VALID_API_STRING.match(blueprint["name"]) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + with api.config["GITLOCK"].lock: + commit_recipe(api.config["GITLOCK"].repo, branch, blueprint) + + # Read the blueprint with new version and write it to the workspace + blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint["name"]) + workspace_write(api.config["GITLOCK"].repo, branch, blueprint) + except Exception as e: + log.error("(v0_blueprints_new) %s", str(e)) + return jsonify(status=False, errors=[{"id": BLUEPRINTS_ERROR, "msg": str(e)}]), 400 + else: + return jsonify(status=True) + + @api.route("/api/v0/blueprints/delete", defaults={'blueprint_name': ""}, methods=["DELETE"]) + @api.route("/api/v0/blueprints/delete/<blueprint_name>", methods=["DELETE"]) + @crossdomain(origin="*") + @checkparams([("blueprint_name", "", "no blueprint name given")]) + def v0_blueprints_delete(blueprint_name): + """Delete a blueprint from git""" + if VALID_API_STRING.match(blueprint_name) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + with api.config["GITLOCK"].lock: + workspace_delete(api.config["GITLOCK"].repo, branch, blueprint_name) + delete_recipe(api.config["GITLOCK"].repo, branch, blueprint_name) + except Exception as e: + log.error("(v0_blueprints_delete) %s", str(e)) + return jsonify(status=False, errors=[{"id": BLUEPRINTS_ERROR, "msg": str(e)}]), 400 + else: + return jsonify(status=True) + + @api.route("/api/v0/blueprints/workspace", methods=["POST"]) + @crossdomain(origin="*") + def v0_blueprints_workspace(): + """Write a blueprint to the workspace""" + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + if request.headers['Content-Type'] == "text/x-toml": + blueprint = recipe_from_toml(request.data) + else: + blueprint = recipe_from_dict(request.get_json(cache=False)) + + if VALID_API_STRING.match(blueprint["name"]) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + with api.config["GITLOCK"].lock: + workspace_write(api.config["GITLOCK"].repo, branch, blueprint) + except Exception as e: + log.error("(v0_blueprints_workspace) %s", str(e)) + return jsonify(status=False, errors=[{"id": BLUEPRINTS_ERROR, "msg": str(e)}]), 400 + else: + return jsonify(status=True) + + @api.route("/api/v0/blueprints/workspace", defaults={'blueprint_name': ""}, methods=["DELETE"]) + @api.route("/api/v0/blueprints/workspace/<blueprint_name>", methods=["DELETE"]) + @crossdomain(origin="*") + @checkparams([("blueprint_name", "", "no blueprint name given")]) + def v0_blueprints_delete_workspace(blueprint_name): + """Delete a blueprint from the workspace""" + if VALID_API_STRING.match(blueprint_name) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + with api.config["GITLOCK"].lock: + workspace_delete(api.config["GITLOCK"].repo, branch, blueprint_name) + except Exception as e: + log.error("(v0_blueprints_delete_workspace) %s", str(e)) + return jsonify(status=False, errors=[{"id": BLUEPRINTS_ERROR, "msg": str(e)}]), 400 + else: + return jsonify(status=True) + + @api.route("/api/v0/blueprints/undo", defaults={'blueprint_name': "", 'commit': ""}, methods=["POST"]) + @api.route("/api/v0/blueprints/undo/<blueprint_name>", defaults={'commit': ""}, methods=["POST"]) + @api.route("/api/v0/blueprints/undo/<blueprint_name>/<commit>", methods=["POST"]) + @crossdomain(origin="*") + @checkparams([("blueprint_name", "", "no blueprint name given"), + ("commit", "", "no commit ID given")]) + def v0_blueprints_undo(blueprint_name, commit): + """Undo changes to a blueprint by reverting to a previous commit.""" + if VALID_API_STRING.match(blueprint_name) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + with api.config["GITLOCK"].lock: + revert_recipe(api.config["GITLOCK"].repo, branch, blueprint_name, commit) + + # Read the new recipe and write it to the workspace + blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + workspace_write(api.config["GITLOCK"].repo, branch, blueprint) + except Exception as e: + log.error("(v0_blueprints_undo) %s", str(e)) + return jsonify(status=False, errors=[{"id": UNKNOWN_COMMIT, "msg": str(e)}]), 400 + else: + return jsonify(status=True) + + @api.route("/api/v0/blueprints/tag", defaults={'blueprint_name': ""}, methods=["POST"]) + @api.route("/api/v0/blueprints/tag/<blueprint_name>", methods=["POST"]) + @crossdomain(origin="*") + @checkparams([("blueprint_name", "", "no blueprint name given")]) + def v0_blueprints_tag(blueprint_name): + """Tag a blueprint's latest blueprint commit as a 'revision'""" + if VALID_API_STRING.match(blueprint_name) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + try: + with api.config["GITLOCK"].lock: + tag_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + except RecipeFileError as e: + log.error("(v0_blueprints_tag) %s", str(e)) + return jsonify(status=False, errors=[{"id": UNKNOWN_BLUEPRINT, "msg": str(e)}]), 400 + except Exception as e: + log.error("(v0_blueprints_tag) %s", str(e)) + return jsonify(status=False, errors=[{"id": BLUEPRINTS_ERROR, "msg": str(e)}]), 400 + else: + return jsonify(status=True) + + @api.route("/api/v0/blueprints/diff", defaults={'blueprint_name': "", 'from_commit': "", 'to_commit': ""}) + @api.route("/api/v0/blueprints/diff/<blueprint_name>", defaults={'from_commit': "", 'to_commit': ""}) + @api.route("/api/v0/blueprints/diff/<blueprint_name>/<from_commit>", defaults={'to_commit': ""}) + @api.route("/api/v0/blueprints/diff/<blueprint_name>/<from_commit>/<to_commit>") + @crossdomain(origin="*") + @checkparams([("blueprint_name", "", "no blueprint name given"), + ("from_commit", "", "no from commit ID given"), + ("to_commit", "", "no to commit ID given")]) + def v0_blueprints_diff(blueprint_name, from_commit, to_commit): + """Return the differences between two commits of a blueprint""" + for s in [blueprint_name, from_commit, to_commit]: + if VALID_API_STRING.match(s) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + if not blueprint_exists(api, branch, blueprint_name): + return jsonify(status=False, errors=[{"id": UNKNOWN_BLUEPRINT, "msg": "Unknown blueprint name: %s" % blueprint_name}]) + + try: + if from_commit == "NEWEST": + with api.config["GITLOCK"].lock: + old_blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + else: + with api.config["GITLOCK"].lock: + old_blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name, from_commit) + except Exception as e: + log.error("(v0_blueprints_diff) %s", str(e)) + return jsonify(status=False, errors=[{"id": UNKNOWN_COMMIT, "msg": str(e)}]), 400 + + try: + if to_commit == "WORKSPACE": + with api.config["GITLOCK"].lock: + new_blueprint = workspace_read(api.config["GITLOCK"].repo, branch, blueprint_name) + # If there is no workspace, use the newest commit instead + if not new_blueprint: + with api.config["GITLOCK"].lock: + new_blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + elif to_commit == "NEWEST": + with api.config["GITLOCK"].lock: + new_blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + else: + with api.config["GITLOCK"].lock: + new_blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name, to_commit) + except Exception as e: + log.error("(v0_blueprints_diff) %s", str(e)) + return jsonify(status=False, errors=[{"id": UNKNOWN_COMMIT, "msg": str(e)}]), 400 + + diff = recipe_diff(old_blueprint, new_blueprint) + return jsonify(diff=diff) + + @api.route("/api/v0/blueprints/freeze", defaults={'blueprint_names': ""}) + @api.route("/api/v0/blueprints/freeze/<blueprint_names>") + @crossdomain(origin="*") + @checkparams([("blueprint_names", "", "no blueprint names given")]) + def v0_blueprints_freeze(blueprint_names): + """Return the blueprint with the exact modules and packages selected by depsolve""" + if VALID_API_STRING.match(blueprint_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + out_fmt = request.args.get("format", "json") + if VALID_API_STRING.match(out_fmt) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in format argument"}]), 400 + + blueprints = [] + errors = [] + for blueprint_name in [n.strip() for n in sorted(blueprint_names.split(","), key=lambda n: n.lower())]: + # get the blueprint + # Get the workspace version (if it exists) + blueprint = None + try: + with api.config["GITLOCK"].lock: + blueprint = workspace_read(api.config["GITLOCK"].repo, branch, blueprint_name) + except Exception: + pass + + if not blueprint: + # No workspace version, get the git version (if it exists) + try: + with api.config["GITLOCK"].lock: + blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + except RecipeFileError as e: + # adding an error here would be redundant, skip it + log.error("(v0_blueprints_freeze) %s", str(e)) + except Exception as e: + errors.append({"id": BLUEPRINTS_ERROR, "msg": "%s: %s" % (blueprint_name, str(e))}) + log.error("(v0_blueprints_freeze) %s", str(e)) + + # No blueprint found, skip it. + if not blueprint: + errors.append({"id": UNKNOWN_BLUEPRINT, "msg": "%s: blueprint_not_found" % blueprint_name}) + continue + + # Combine modules and packages and depsolve the list + # TODO include the version/glob in the depsolving + module_nver = blueprint.module_nver + package_nver = blueprint.package_nver + projects = sorted(set(module_nver+package_nver), key=lambda p: p[0].lower()) + deps = [] + try: + with api.config["DNFLOCK"].lock: + deps = projects_depsolve(api.config["DNFLOCK"].dbo, projects, blueprint.group_names) + except ProjectsError as e: + errors.append({"id": BLUEPRINTS_ERROR, "msg": "%s: %s" % (blueprint_name, str(e))}) + log.error("(v0_blueprints_freeze) %s", str(e)) + + blueprints.append({"blueprint": blueprint.freeze(deps)}) + + if out_fmt == "toml": + # With TOML output we just want to dump the raw blueprint, skipping the rest. + return "\n\n".join([e["blueprint"].toml() for e in blueprints]) + else: + return jsonify(blueprints=blueprints, errors=errors) + + @api.route("/api/v0/blueprints/depsolve", defaults={'blueprint_names': ""}) + @api.route("/api/v0/blueprints/depsolve/<blueprint_names>") + @crossdomain(origin="*") + @checkparams([("blueprint_names", "", "no blueprint names given")]) + def v0_blueprints_depsolve(blueprint_names): + """Return the dependencies for a blueprint""" + if VALID_API_STRING.match(blueprint_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + branch = request.args.get("branch", "master") + if VALID_API_STRING.match(branch) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in branch argument"}]), 400 + + blueprints = [] + errors = [] + for blueprint_name in [n.strip() for n in sorted(blueprint_names.split(","), key=lambda n: n.lower())]: + # get the blueprint + # Get the workspace version (if it exists) + blueprint = None + try: + with api.config["GITLOCK"].lock: + blueprint = workspace_read(api.config["GITLOCK"].repo, branch, blueprint_name) + except Exception: + pass + + if not blueprint: + # No workspace version, get the git version (if it exists) + try: + with api.config["GITLOCK"].lock: + blueprint = read_recipe_commit(api.config["GITLOCK"].repo, branch, blueprint_name) + except RecipeFileError as e: + # adding an error here would be redundant, skip it + log.error("(v0_blueprints_depsolve) %s", str(e)) + except Exception as e: + errors.append({"id": BLUEPRINTS_ERROR, "msg": "%s: %s" % (blueprint_name, str(e))}) + log.error("(v0_blueprints_depsolve) %s", str(e)) + + # No blueprint found, skip it. + if not blueprint: + errors.append({"id": UNKNOWN_BLUEPRINT, "msg": "%s: blueprint not found" % blueprint_name}) + continue + + # Combine modules and packages and depsolve the list + # TODO include the version/glob in the depsolving + module_nver = blueprint.module_nver + package_nver = blueprint.package_nver + projects = sorted(set(module_nver+package_nver), key=lambda p: p[0].lower()) + deps = [] + try: + with api.config["DNFLOCK"].lock: + deps = projects_depsolve(api.config["DNFLOCK"].dbo, projects, blueprint.group_names) + except ProjectsError as e: + errors.append({"id": BLUEPRINTS_ERROR, "msg": "%s: %s" % (blueprint_name, str(e))}) + log.error("(v0_blueprints_depsolve) %s", str(e)) + + # Get the NEVRA's of the modules and projects, add as "modules" + modules = [] + for dep in deps: + if dep["name"] in projects: + modules.append(dep) + modules = sorted(modules, key=lambda m: m["name"].lower()) + + blueprints.append({"blueprint":blueprint, "dependencies":deps, "modules":modules}) + + return jsonify(blueprints=blueprints, errors=errors) + + @api.route("/api/v0/projects/list") + @crossdomain(origin="*") + def v0_projects_list(): + """List all of the available projects/packages""" + try: + limit = int(request.args.get("limit", "20")) + offset = int(request.args.get("offset", "0")) + except ValueError as e: + return jsonify(status=False, errors=[{"id": BAD_LIMIT_OR_OFFSET, "msg": str(e)}]), 400 + + try: + with api.config["DNFLOCK"].lock: + available = projects_list(api.config["DNFLOCK"].dbo) + except ProjectsError as e: + log.error("(v0_projects_list) %s", str(e)) + return jsonify(status=False, errors=[{"id": PROJECTS_ERROR, "msg": str(e)}]), 400 + + projects = take_limits(available, offset, limit) + return jsonify(projects=projects, offset=offset, limit=limit, total=len(available)) + + @api.route("/api/v0/projects/info", defaults={'project_names': ""}) + @api.route("/api/v0/projects/info/<project_names>") + @crossdomain(origin="*") + @checkparams([("project_names", "", "no project names given")]) + def v0_projects_info(project_names): + """Return detailed information about the listed projects""" + if VALID_API_STRING.match(project_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + try: + with api.config["DNFLOCK"].lock: + projects = projects_info(api.config["DNFLOCK"].dbo, project_names.split(",")) + except ProjectsError as e: + log.error("(v0_projects_info) %s", str(e)) + return jsonify(status=False, errors=[{"id": PROJECTS_ERROR, "msg": str(e)}]), 400 + + if not projects: + msg = "one of the requested projects does not exist: %s" % project_names + log.error("(v0_projects_info) %s", msg) + return jsonify(status=False, errors=[{"id": UNKNOWN_PROJECT, "msg": msg}]), 400 + + return jsonify(projects=projects) + + @api.route("/api/v0/projects/depsolve", defaults={'project_names': ""}) + @api.route("/api/v0/projects/depsolve/<project_names>") + @crossdomain(origin="*") + @checkparams([("project_names", "", "no project names given")]) + def v0_projects_depsolve(project_names): + """Return detailed information about the listed projects""" + if VALID_API_STRING.match(project_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + try: + with api.config["DNFLOCK"].lock: + deps = projects_depsolve(api.config["DNFLOCK"].dbo, [(n, "*") for n in project_names.split(",")], []) + except ProjectsError as e: + log.error("(v0_projects_depsolve) %s", str(e)) + return jsonify(status=False, errors=[{"id": PROJECTS_ERROR, "msg": str(e)}]), 400 + + if not deps: + msg = "one of the requested projects does not exist: %s" % project_names + log.error("(v0_projects_depsolve) %s", msg) + return jsonify(status=False, errors=[{"id": UNKNOWN_PROJECT, "msg": msg}]), 400 + + return jsonify(projects=deps) + + @api.route("/api/v0/projects/source/list") + @crossdomain(origin="*") + def v0_projects_source_list(): + """Return the list of source names""" + with api.config["DNFLOCK"].lock: + repos = list(api.config["DNFLOCK"].dbo.repos.iter_enabled()) + sources = sorted([r.id for r in repos]) + return jsonify(sources=sources) + + @api.route("/api/v0/projects/source/info", defaults={'source_names': ""}) + @api.route("/api/v0/projects/source/info/<source_names>") + @crossdomain(origin="*") + @checkparams([("source_names", "", "no source names given")]) + def v0_projects_source_info(source_names): + """Return detailed info about the list of sources""" + if VALID_API_STRING.match(source_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + out_fmt = request.args.get("format", "json") + if VALID_API_STRING.match(out_fmt) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in format argument"}]), 400 + + # Return info on all of the sources + if source_names == "*": + with api.config["DNFLOCK"].lock: + source_names = ",".join(r.id for r in api.config["DNFLOCK"].dbo.repos.iter_enabled()) + + sources = {} + errors = [] + system_sources = get_repo_sources("/etc/yum.repos.d/*.repo") + for source in source_names.split(","): + with api.config["DNFLOCK"].lock: + repo = api.config["DNFLOCK"].dbo.repos.get(source, None) + if not repo: + errors.append({"id": UNKNOWN_SOURCE, "msg": "%s is not a valid source" % source}) + continue + sources[repo.id] = repo_to_source(repo, repo.id in system_sources) + + if out_fmt == "toml" and not errors: + # With TOML output we just want to dump the raw sources, skipping the errors + return toml.dumps(sources) + elif out_fmt == "toml" and errors: + # TOML requested, but there was an error + return jsonify(status=False, errors=errors), 400 + else: + return jsonify(sources=sources, errors=errors) + + @api.route("/api/v0/projects/source/new", methods=["POST"]) + @crossdomain(origin="*") + def v0_projects_source_new(): + """Add a new package source. Or change an existing one""" + if request.headers['Content-Type'] == "text/x-toml": + source = toml.loads(request.data) + else: + source = request.get_json(cache=False) + + system_sources = get_repo_sources("/etc/yum.repos.d/*.repo") + if source["name"] in system_sources: + return jsonify(status=False, errors=[{"id": SYSTEM_SOURCE, "msg": "%s is a system source, it cannot be changed." % source["name"]}]), 400 + + try: + # Remove it from the RepoDict (NOTE that this isn't explicitly supported by the DNF API) + with api.config["DNFLOCK"].lock: + dbo = api.config["DNFLOCK"].dbo + # If this repo already exists, delete it and replace it with the new one + repos = list(r.id for r in dbo.repos.iter_enabled()) + if source["name"] in repos: + del dbo.repos[source["name"]] + + repo = source_to_repo(source, dbo.conf) + dbo.repos.add(repo) + + log.info("Updating repository metadata after adding %s", source["name"]) + dbo.fill_sack(load_system_repo=False) + dbo.read_comps() + + # Write the new repo to disk, replacing any existing ones + repo_dir = api.config["COMPOSER_CFG"].get("composer", "repo_dir") + + # Remove any previous sources with this name, ignore it if it isn't found + try: + delete_repo_source(joinpaths(repo_dir, "*.repo"), source["name"]) + except ProjectsError: + pass + + # Make sure the source name can't contain a path traversal by taking the basename + source_path = joinpaths(repo_dir, os.path.basename("%s.repo" % source["name"])) + with open(source_path, "w") as f: + f.write(dnf_repo_to_file_repo(repo)) + except Exception as e: + log.error("(v0_projects_source_add) adding %s failed: %s", source["name"], str(e)) + + # Cleanup the mess, if loading it failed we don't want to leave it in memory + repos = list(r.id for r in dbo.repos.iter_enabled()) + if source["name"] in repos: + with api.config["DNFLOCK"].lock: + dbo = api.config["DNFLOCK"].dbo + del dbo.repos[source["name"]] + + log.info("Updating repository metadata after adding %s failed", source["name"]) + dbo.fill_sack(load_system_repo=False) + dbo.read_comps() + + return jsonify(status=False, errors=[{"id": PROJECTS_ERROR, "msg": str(e)}]), 400 + + return jsonify(status=True) + + @api.route("/api/v0/projects/source/delete", defaults={'source_name': ""}, methods=["DELETE"]) + @api.route("/api/v0/projects/source/delete/<source_name>", methods=["DELETE"]) + @crossdomain(origin="*") + @checkparams([("source_name", "", "no source name given")]) + def v0_projects_source_delete(source_name): + """Delete the named source and return a status response""" + if VALID_API_STRING.match(source_name) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + system_sources = get_repo_sources("/etc/yum.repos.d/*.repo") + if source_name in system_sources: + return jsonify(status=False, errors=[{"id": SYSTEM_SOURCE, "msg": "%s is a system source, it cannot be deleted." % source_name}]), 400 + share_dir = api.config["COMPOSER_CFG"].get("composer", "repo_dir") + try: + # Remove the file entry for the source + delete_repo_source(joinpaths(share_dir, "*.repo"), source_name) + + # Remove it from the RepoDict (NOTE that this isn't explicitly supported by the DNF API) + with api.config["DNFLOCK"].lock: + if source_name in api.config["DNFLOCK"].dbo.repos: + del api.config["DNFLOCK"].dbo.repos[source_name] + log.info("Updating repository metadata after removing %s", source_name) + api.config["DNFLOCK"].dbo.fill_sack(load_system_repo=False) + api.config["DNFLOCK"].dbo.read_comps() + + except ProjectsError as e: + log.error("(v0_projects_source_delete) %s", str(e)) + return jsonify(status=False, errors=[{"id": UNKNOWN_SOURCE, "msg": str(e)}]), 400 + + return jsonify(status=True) + + @api.route("/api/v0/modules/list") + @api.route("/api/v0/modules/list/<module_names>") + @crossdomain(origin="*") + def v0_modules_list(module_names=None): + """List available modules, filtering by module_names""" + if module_names and VALID_API_STRING.match(module_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + try: + limit = int(request.args.get("limit", "20")) + offset = int(request.args.get("offset", "0")) + except ValueError as e: + return jsonify(status=False, errors=[{"id": BAD_LIMIT_OR_OFFSET, "msg": str(e)}]), 400 + + if module_names: + module_names = module_names.split(",") + + try: + with api.config["DNFLOCK"].lock: + available = modules_list(api.config["DNFLOCK"].dbo, module_names) + except ProjectsError as e: + log.error("(v0_modules_list) %s", str(e)) + return jsonify(status=False, errors=[{"id": MODULES_ERROR, "msg": str(e)}]), 400 + + if module_names and not available: + msg = "one of the requested modules does not exist: %s" % module_names + log.error("(v0_modules_list) %s", msg) + return jsonify(status=False, errors=[{"id": UNKNOWN_MODULE, "msg": msg}]), 400 + + modules = take_limits(available, offset, limit) + return jsonify(modules=modules, offset=offset, limit=limit, total=len(available)) + + @api.route("/api/v0/modules/info", defaults={'module_names': ""}) + @api.route("/api/v0/modules/info/<module_names>") + @crossdomain(origin="*") + @checkparams([("module_names", "", "no module names given")]) + def v0_modules_info(module_names): + """Return detailed information about the listed modules""" + if VALID_API_STRING.match(module_names) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + try: + with api.config["DNFLOCK"].lock: + modules = modules_info(api.config["DNFLOCK"].dbo, module_names.split(",")) + except ProjectsError as e: + log.error("(v0_modules_info) %s", str(e)) + return jsonify(status=False, errors=[{"id": MODULES_ERROR, "msg": str(e)}]), 400 + + if not modules: + msg = "one of the requested modules does not exist: %s" % module_names + log.error("(v0_modules_info) %s", msg) + return jsonify(status=False, errors=[{"id": UNKNOWN_MODULE, "msg": msg}]), 400 + + return jsonify(modules=modules) + + @api.route("/api/v0/compose", methods=["POST"]) + @crossdomain(origin="*") + def v0_compose_start(): + """Start a compose + + The body of the post should have these fields: + blueprint_name - The blueprint name from /blueprints/list/ + compose_type - The type of output to create, from /compose/types + branch - Optional, defaults to master, selects the git branch to use for the blueprint. + """ + # Passing ?test=1 will generate a fake FAILED compose. + # Passing ?test=2 will generate a fake FINISHED compose. + try: + test_mode = int(request.args.get("test", "0")) + except ValueError: + test_mode = 0 + + compose = request.get_json(cache=False) + + errors = [] + if not compose: + return jsonify(status=False, errors=[{"id": MISSING_POST, "msg": "Missing POST body"}]), 400 + + if "blueprint_name" not in compose: + errors.append({"id": UNKNOWN_BLUEPRINT,"msg": "No 'blueprint_name' in the JSON request"}) + else: + blueprint_name = compose["blueprint_name"] + + if "branch" not in compose or not compose["branch"]: + branch = "master" + else: + branch = compose["branch"] + + if "compose_type" not in compose: + errors.append({"id": BAD_COMPOSE_TYPE, "msg": "No 'compose_type' in the JSON request"}) + else: + compose_type = compose["compose_type"] + + if VALID_API_STRING.match(blueprint_name) is None: + errors.append({"id": INVALID_CHARS, "msg": "Invalid characters in API path"}) + + if not blueprint_exists(api, branch, blueprint_name): + errors.append({"id": UNKNOWN_BLUEPRINT, "msg": "Unknown blueprint name: %s" % blueprint_name}) + + if errors: + return jsonify(status=False, errors=errors), 400 + + try: + build_id = start_build(api.config["COMPOSER_CFG"], api.config["DNFLOCK"], api.config["GITLOCK"], + branch, blueprint_name, compose_type, test_mode) + except Exception as e: + if "Invalid compose type" in str(e): + return jsonify(status=False, errors=[{"id": BAD_COMPOSE_TYPE, "msg": str(e)}]), 400 + else: + return jsonify(status=False, errors=[{"id": BUILD_FAILED, "msg": str(e)}]), 400 + + return jsonify(status=True, build_id=build_id) + + @api.route("/api/v0/compose/types") + @crossdomain(origin="*") + def v0_compose_types(): + """Return the list of enabled output types + + (only enabled types are returned) + """ + share_dir = api.config["COMPOSER_CFG"].get("composer", "share_dir") + return jsonify(types=[{"name": k, "enabled": True} for k in compose_types(share_dir)]) + + @api.route("/api/v0/compose/queue") + @crossdomain(origin="*") + def v0_compose_queue(): + """Return the status of the new and running queues""" + return jsonify(queue_status(api.config["COMPOSER_CFG"])) + + @api.route("/api/v0/compose/finished") + @crossdomain(origin="*") + def v0_compose_finished(): + """Return the list of finished composes""" + return jsonify(finished=build_status(api.config["COMPOSER_CFG"], "FINISHED")) + + @api.route("/api/v0/compose/failed") + @crossdomain(origin="*") + def v0_compose_failed(): + """Return the list of failed composes""" + return jsonify(failed=build_status(api.config["COMPOSER_CFG"], "FAILED")) + + @api.route("/api/v0/compose/status", defaults={'uuids': ""}) + @api.route("/api/v0/compose/status/<uuids>") + @crossdomain(origin="*") + @checkparams([("uuids", "", "no UUIDs given")]) + def v0_compose_status(uuids): + """Return the status of the listed uuids""" + if VALID_API_STRING.match(uuids) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + blueprint = request.args.get("blueprint", None) + status = request.args.get("status", None) + compose_type = request.args.get("type", None) + + results = [] + errors = [] + + if uuids.strip() == '*': + queue_status_dict = queue_status(api.config["COMPOSER_CFG"]) + queue_new = queue_status_dict["new"] + queue_running = queue_status_dict["run"] + candidates = queue_new + queue_running + build_status(api.config["COMPOSER_CFG"]) + else: + candidates = [] + for uuid in [n.strip().lower() for n in uuids.split(",")]: + details = uuid_status(api.config["COMPOSER_CFG"], uuid) + if details is None: + errors.append({"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}) + else: + candidates.append(details) + + for details in candidates: + if blueprint is not None and details['blueprint'] != blueprint: + continue + + if status is not None and details['queue_status'] != status: + continue + + if compose_type is not None and details['compose_type'] != compose_type: + continue + + results.append(details) + + return jsonify(uuids=results, errors=errors) + + @api.route("/api/v0/compose/cancel", defaults={'uuid': ""}, methods=["DELETE"]) + @api.route("/api/v0/compose/cancel/<uuid>", methods=["DELETE"]) + @crossdomain(origin="*") + @checkparams([("uuid", "", "no UUID given")]) + def v0_compose_cancel(uuid): + """Cancel a running compose and delete its results directory""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + + if status["queue_status"] not in ["WAITING", "RUNNING"]: + return jsonify(status=False, errors=[{"id": BUILD_IN_WRONG_STATE, "msg": "Build %s is not in WAITING or RUNNING." % uuid}]) + + try: + uuid_cancel(api.config["COMPOSER_CFG"], uuid) + except Exception as e: + return jsonify(status=False, errors=[{"id": COMPOSE_ERROR, "msg": "%s: %s" % (uuid, str(e))}]),400 + else: + return jsonify(status=True, uuid=uuid) + + @api.route("/api/v0/compose/delete", defaults={'uuids': ""}, methods=["DELETE"]) + @api.route("/api/v0/compose/delete/<uuids>", methods=["DELETE"]) + @crossdomain(origin="*") + @checkparams([("uuids", "", "no UUIDs given")]) + def v0_compose_delete(uuids): + """Delete the compose results for the listed uuids""" + if VALID_API_STRING.match(uuids) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + results = [] + errors = [] + for uuid in [n.strip().lower() for n in uuids.split(",")]: + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + errors.append({"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}) + elif status["queue_status"] not in ["FINISHED", "FAILED"]: + errors.append({"id": BUILD_IN_WRONG_STATE, "msg": "Build %s is not in FINISHED or FAILED." % uuid}) + else: + try: + uuid_delete(api.config["COMPOSER_CFG"], uuid) + except Exception as e: + errors.append({"id": COMPOSE_ERROR, "msg": "%s: %s" % (uuid, str(e))}) + else: + results.append({"uuid":uuid, "status":True}) + return jsonify(uuids=results, errors=errors) + + @api.route("/api/v0/compose/info", defaults={'uuid': ""}) + @api.route("/api/v0/compose/info/<uuid>") + @crossdomain(origin="*") + @checkparams([("uuid", "", "no UUID given")]) + def v0_compose_info(uuid): + """Return detailed info about a compose""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + try: + info = uuid_info(api.config["COMPOSER_CFG"], uuid) + except Exception as e: + return jsonify(status=False, errors=[{"id": COMPOSE_ERROR, "msg": str(e)}]), 400 + + if info is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + else: + return jsonify(**info) + + @api.route("/api/v0/compose/metadata", defaults={'uuid': ""}) + @api.route("/api/v0/compose/metadata/<uuid>") + @crossdomain(origin="*") + @checkparams([("uuid","", "no UUID given")]) + def v0_compose_metadata(uuid): + """Return a tar of the metadata for the build""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + if status["queue_status"] not in ["FINISHED", "FAILED"]: + return jsonify(status=False, errors=[{"id": BUILD_IN_WRONG_STATE, "msg": "Build %s not in FINISHED or FAILED state." % uuid}]), 400 + else: + return Response(uuid_tar(api.config["COMPOSER_CFG"], uuid, metadata=True, image=False, logs=False), + mimetype="application/x-tar", + headers=[("Content-Disposition", "attachment; filename=%s-metadata.tar;" % uuid)], + direct_passthrough=True) + + @api.route("/api/v0/compose/results", defaults={'uuid': ""}) + @api.route("/api/v0/compose/results/<uuid>") + @crossdomain(origin="*") + @checkparams([("uuid","", "no UUID given")]) + def v0_compose_results(uuid): + """Return a tar of the metadata and the results for the build""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + elif status["queue_status"] not in ["FINISHED", "FAILED"]: + return jsonify(status=False, errors=[{"id": BUILD_IN_WRONG_STATE, "msg": "Build %s not in FINISHED or FAILED state." % uuid}]), 400 + else: + return Response(uuid_tar(api.config["COMPOSER_CFG"], uuid, metadata=True, image=True, logs=True), + mimetype="application/x-tar", + headers=[("Content-Disposition", "attachment; filename=%s.tar;" % uuid)], + direct_passthrough=True) + + @api.route("/api/v0/compose/logs", defaults={'uuid': ""}) + @api.route("/api/v0/compose/logs/<uuid>") + @crossdomain(origin="*") + @checkparams([("uuid","", "no UUID given")]) + def v0_compose_logs(uuid): + """Return a tar of the metadata for the build""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + elif status["queue_status"] not in ["FINISHED", "FAILED"]: + return jsonify(status=False, errors=[{"id": BUILD_IN_WRONG_STATE, "msg": "Build %s not in FINISHED or FAILED state." % uuid}]), 400 + else: + return Response(uuid_tar(api.config["COMPOSER_CFG"], uuid, metadata=False, image=False, logs=True), + mimetype="application/x-tar", + headers=[("Content-Disposition", "attachment; filename=%s-logs.tar;" % uuid)], + direct_passthrough=True) + + @api.route("/api/v0/compose/image", defaults={'uuid': ""}) + @api.route("/api/v0/compose/image/<uuid>") + @crossdomain(origin="*") + @checkparams([("uuid","", "no UUID given")]) + def v0_compose_image(uuid): + """Return the output image for the build""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + elif status["queue_status"] not in ["FINISHED", "FAILED"]: + return jsonify(status=False, errors=[{"id": BUILD_IN_WRONG_STATE, "msg": "Build %s not in FINISHED or FAILED state." % uuid}]), 400 + else: + image_name, image_path = uuid_image(api.config["COMPOSER_CFG"], uuid) + + # Make sure it really exists + if not os.path.exists(image_path): + return jsonify(status=False, errors=[{"id": BUILD_MISSING_FILE, "msg": "Build %s is missing image file %s" % (uuid, image_name)}]), 400 + + # Make the image name unique + image_name = uuid + "-" + image_name + # XXX - Will mime type guessing work for all our output? + return send_file(image_path, as_attachment=True, attachment_filename=image_name, add_etags=False) + + @api.route("/api/v0/compose/log", defaults={'uuid': ""}) + @api.route("/api/v0/compose/log/<uuid>") + @crossdomain(origin="*") + @checkparams([("uuid","", "no UUID given")]) + def v0_compose_log_tail(uuid): + """Return the end of the main anaconda.log, defaults to 1Mbytes""" + if VALID_API_STRING.match(uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + try: + size = int(request.args.get("size", "1024")) + except ValueError as e: + return jsonify(status=False, errors=[{"id": COMPOSE_ERROR, "msg": str(e)}]), 400 + + status = uuid_status(api.config["COMPOSER_CFG"], uuid) + if status is None: + return jsonify(status=False, errors=[{"id": UNKNOWN_UUID, "msg": "%s is not a valid build uuid" % uuid}]), 400 + elif status["queue_status"] == "WAITING": + return jsonify(status=False, errors=[{"id": BUILD_IN_WRONG_STATE, "msg": "Build %s has not started yet. No logs to view" % uuid}]) + try: + return Response(uuid_log(api.config["COMPOSER_CFG"], uuid, size), direct_passthrough=True) + except RuntimeError as e: + return jsonify(status=False, errors=[{"id": COMPOSE_ERROR, "msg": str(e)}]), 400
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/api/workspace.html b/f29-branch/_modules/pylorax/api/workspace.html new file mode 100644 index 00000000..a371b6a3 --- /dev/null +++ b/f29-branch/_modules/pylorax/api/workspace.html @@ -0,0 +1,316 @@ + + + + + + + + + + + pylorax.api.workspace — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.workspace

+#
+# Copyright (C) 2017  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, see <http://www.gnu.org/licenses/>.
+#
+import os
+
+from pylorax.api.recipes import recipe_filename, recipe_from_toml, RecipeFileError
+from pylorax.sysutils import joinpaths
+
+
+
[docs]def workspace_dir(repo, branch): + """Create the workspace's path from a Repository and branch + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :returns: The path to the branch's workspace directory + :rtype: str + + """ + repo_path = repo.get_location().get_path() + return joinpaths(repo_path, "workspace", branch)
+ + +
[docs]def workspace_read(repo, branch, recipe_name): + """Read a Recipe from the branch's workspace + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: The name of the recipe + :type recipe_name: str + :returns: The workspace copy of the recipe, or None if it doesn't exist + :rtype: Recipe or None + :raises: RecipeFileError + """ + ws_dir = workspace_dir(repo, branch) + if not os.path.isdir(ws_dir): + os.makedirs(ws_dir) + filename = joinpaths(ws_dir, recipe_filename(recipe_name)) + if not os.path.exists(filename): + return None + try: + f = open(filename, 'rb') + recipe = recipe_from_toml(f.read().decode("UTF-8")) + except IOError: + raise RecipeFileError + return recipe
+ + +
[docs]def workspace_write(repo, branch, recipe): + """Write a recipe to the workspace + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe: The recipe to write to the workspace + :type recipe: Recipe + :returns: None + :raises: IO related errors + """ + ws_dir = workspace_dir(repo, branch) + if not os.path.isdir(ws_dir): + os.makedirs(ws_dir) + filename = joinpaths(ws_dir, recipe.filename) + open(filename, 'wb').write(recipe.toml().encode("UTF-8"))
+ + +
[docs]def workspace_delete(repo, branch, recipe_name): + """Delete the recipe from the workspace + + :param repo: Open repository + :type repo: Git.Repository + :param branch: Branch name + :type branch: str + :param recipe_name: The name of the recipe + :type recipe_name: str + :returns: None + :raises: IO related errors + """ + ws_dir = workspace_dir(repo, branch) + filename = joinpaths(ws_dir, recipe_filename(recipe_name)) + if os.path.exists(filename): + os.unlink(filename)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/base.html b/f29-branch/_modules/pylorax/base.html new file mode 100644 index 00000000..6946180b --- /dev/null +++ b/f29-branch/_modules/pylorax/base.html @@ -0,0 +1,284 @@ + + + + + + + + + + + pylorax.base — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.base

+#
+# base.py
+#
+# Copyright (C) 2009-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#
+
+from abc import ABCMeta, abstractmethod
+import sys
+
+import pylorax.output as output
+
+
+
[docs]class BaseLoraxClass(object, metaclass=ABCMeta): + @abstractmethod + def __init__(self): + self.output = output.LoraxOutput() + +
[docs] def pcritical(self, msg, fobj=sys.stdout): + self.output.critical(msg, fobj)
+ +
[docs] def perror(self, msg, fobj=sys.stdout): + self.output.error(msg, fobj)
+ +
[docs] def pwarning(self, msg, fobj=sys.stdout): + self.output.warning(msg, fobj)
+ +
[docs] def pinfo(self, msg, fobj=sys.stdout): + self.output.info(msg, fobj)
+ +
[docs] def pdebug(self, msg, fobj=sys.stdout): + self.output.debug(msg, fobj)
+ + +
[docs]class DataHolder(dict): + + def __init__(self, **kwargs): + dict.__init__(self) + + for attr, value in kwargs.items(): + self[attr] = value + + def __getattr__(self, attr): + if attr in self: + return self[attr] + else: + raise AttributeError + + def __setattr__(self, attr, value): + self[attr] = value + +
[docs] def copy(self): + return DataHolder(**dict.copy(self))
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/buildstamp.html b/f29-branch/_modules/pylorax/buildstamp.html new file mode 100644 index 00000000..ce4d60cc --- /dev/null +++ b/f29-branch/_modules/pylorax/buildstamp.html @@ -0,0 +1,283 @@ + + + + + + + + + + + pylorax.buildstamp — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.buildstamp

+#
+# buildstamp.py
+#
+# Copyright (C) 2010-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#
+
+import logging
+logger = logging.getLogger("pylorax.buildstamp")
+
+import datetime
+import os
+
+
+
[docs]class BuildStamp(object): + + def __init__(self, product, version, bugurl, isfinal, buildarch, variant=""): + self.product = product + self.version = version + self.bugurl = bugurl + self.isfinal = isfinal + self.variant = variant + + if 'SOURCE_DATE_EPOCH' in os.environ: + now = datetime.datetime.utcfromtimestamp( + int(os.environ['SOURCE_DATE_EPOCH'])) + else: + now = datetime.datetime.now() + now = now.strftime("%Y%m%d%H%M") + self.uuid = "{0}.{1}".format(now, buildarch) + +
[docs] def write(self, outfile): + # get lorax version + try: + import pylorax.version + except ImportError: + vernum = "devel" + else: + vernum = pylorax.version.num + + logger.info("writing .buildstamp file") + with open(outfile, "w") as fobj: + fobj.write("[Main]\n") + fobj.write("Product={0.product}\n".format(self)) + fobj.write("Version={0.version}\n".format(self)) + fobj.write("BugURL={0.bugurl}\n".format(self)) + fobj.write("IsFinal={0.isfinal}\n".format(self)) + fobj.write("UUID={0.uuid}\n".format(self)) + if self.variant: + fobj.write("Variant={0.variant}\n".format(self)) + fobj.write("[Compose]\n") + fobj.write("Lorax={0}\n".format(vernum))
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/cmdline.html b/f29-branch/_modules/pylorax/cmdline.html new file mode 100644 index 00000000..88512346 --- /dev/null +++ b/f29-branch/_modules/pylorax/cmdline.html @@ -0,0 +1,532 @@ + + + + + + + + + + + pylorax.cmdline — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.cmdline

+#
+# cmdline.py
+#
+# Copyright (C) 2016  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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Brian C. Lane <bcl@redhat.com>
+
+import os
+import sys
+import argparse
+
+from pylorax import vernum
+
+version = "{0}-{1}".format(os.path.basename(sys.argv[0]), vernum)
+
+
[docs]def lorax_parser(dracut_default=""): + """ Return the ArgumentParser for lorax""" + + parser = argparse.ArgumentParser(description="Create the Anaconda boot.iso") + + # required arguments for image creation + required = parser.add_argument_group("required arguments") + required.add_argument("-p", "--product", help="product name", required=True, metavar="PRODUCT") + required.add_argument("-v", "--version", help="version identifier", required=True, metavar="VERSION") + required.add_argument("-r", "--release", help="release information", required=True, metavar="RELEASE") + required.add_argument("-s", "--source", help="source repository (may be listed multiple times)", + metavar="REPOSITORY", action="append", default=[]) + required.add_argument("--repo", help="source dnf repository file", type=os.path.abspath, + dest="repos", metavar="REPOSITORY", action="append", default=[]) + + # optional arguments + optional = parser.add_argument_group("optional arguments") + optional.add_argument("-m", "--mirrorlist", + help="mirrorlist repository (may be listed multiple times)", + metavar="REPOSITORY", action="append", default=[]) + optional.add_argument("-t", "--variant", default="", + help="variant name", metavar="VARIANT") + optional.add_argument("-b", "--bugurl", + help="bug reporting URL for the product", metavar="URL", + default="your distribution provided bug reporting tool") + optional.add_argument("--isfinal", help="", + action="store_true", default=False, dest="isfinal") + optional.add_argument("-c", "--config", default="/etc/lorax/lorax.conf", + help="config file", metavar="CONFIGFILE") + optional.add_argument("--proxy", default=None, + help="repo proxy url:port", metavar="HOST") + optional.add_argument("-i", "--installpkgs", default=[], + action="append", metavar="PACKAGE", + help="package glob to install before runtime-install.tmpl runs. (may be listed multiple times)") + optional.add_argument("-e", "--excludepkgs", default=[], + action="append", metavar="PACKAGE", + help="package glob to remove before runtime-install.tmpl runs. (may be listed multiple times)") + optional.add_argument("--buildarch", default=None, + help="build architecture", metavar="ARCH") + optional.add_argument("--volid", default=None, + help="volume id", metavar="VOLID") + optional.add_argument("--macboot", help="", + action="store_true", default=True, dest="domacboot") + optional.add_argument("--nomacboot", help="", + action="store_false", dest="domacboot") + optional.add_argument("--noupgrade", help="", + action="store_false", default=True, dest="doupgrade") + optional.add_argument("--logfile", default="./lorax.log", type=os.path.abspath, + help="Path to logfile") + optional.add_argument("--tmp", default="/var/tmp/lorax", + help="Top level temporary directory" ) + optional.add_argument("--cachedir", default=None, type=os.path.abspath, + help="DNF cache directory. Default is a temporary dir.") + optional.add_argument("--workdir", default=None, type=os.path.abspath, + help="Work directory, overrides --tmp. Default is a temporary dir under /var/tmp/lorax") + optional.add_argument("--force", default=False, action="store_true", + help="Run even when the destination directory exists") + optional.add_argument("--add-template", dest="add_templates", + action="append", help="Additional template for runtime image", + default=[]) + optional.add_argument("--add-template-var", dest="add_template_vars", + action="append", help="Set variable for runtime image template", + default=[]) + optional.add_argument("--add-arch-template", dest="add_arch_templates", + action="append", help="Additional template for architecture-specific image", + default=[]) + optional.add_argument("--add-arch-template-var", dest="add_arch_template_vars", + action="append", help="Set variable for architecture-specific image", + default=[]) + optional.add_argument("--noverify", action="store_false", default=True, dest="verify", + help="Do not verify the install root") + optional.add_argument("--sharedir", metavar="SHAREDIR", type=os.path.abspath, + help="Directory containing all the templates. Overrides config file sharedir") + optional.add_argument("--enablerepo", action="append", default=[], dest="enablerepos", + metavar="[repo]", help="Names of repos to enable") + optional.add_argument("--disablerepo", action="append", default=[], dest="disablerepos", + metavar="[repo]", help="Names of repos to disable") + optional.add_argument("--rootfs-size", type=int, default=2, + help="Size of root filesystem in GiB. Defaults to 2.") + optional.add_argument("--noverifyssl", action="store_true", default=False, + help="Do not verify SSL certificates") + optional.add_argument("--dnfplugin", action="append", default=[], dest="dnfplugins", + help="Enable a DNF plugin by name/glob, or * to enable all of them.") + optional.add_argument("--squashfs-only", action="store_true", default=False, + help="Use a plain squashfs filesystem for the runtime.") + + # dracut arguments + dracut_group = parser.add_argument_group("dracut arguments") + dracut_group.add_argument("--dracut-arg", action="append", dest="dracut_args", + help="Argument to pass to dracut when " + "rebuilding the initramfs. Pass this " + "once for each argument. NOTE: this " + "overrides the default. (default: %s)" % dracut_default) + + # add the show version option + parser.add_argument("-V", help="show program's version number and exit", + action="version", version=version) + + parser.add_argument("outputdir", help="Output directory", metavar="OUTPUTDIR", type=os.path.abspath) + + return parser
+ + +
[docs]def lmc_parser(dracut_default=""): + """ Return a ArgumentParser object for live-media-creator.""" + parser = argparse.ArgumentParser(description="Create Live Install Media", + fromfile_prefix_chars="@") + + # These are mutually exclusive, one is required + action = parser.add_mutually_exclusive_group(required=True) + action.add_argument("--make-iso", action="store_true", + help="Build a live iso") + action.add_argument("--make-disk", action="store_true", + help="Build a partitioned disk image") + action.add_argument("--make-fsimage", action="store_true", + help="Build a filesystem image") + action.add_argument("--make-appliance", action="store_true", + help="Build an appliance image and XML description") + action.add_argument("--make-ami", action="store_true", + help="Build an ami image") + action.add_argument("--make-tar", action="store_true", + help="Build a tar of the root filesystem") + action.add_argument("--make-tar-disk", action="store_true", + help="Build a tar of a partitioned disk image") + action.add_argument("--make-pxe-live", action="store_true", + help="Build a live pxe boot squashfs image") + action.add_argument("--make-ostree-live", action="store_true", + help="Build a live pxe boot squashfs image of Atomic Host") + action.add_argument("--make-oci", action="store_true", + help="Build an Open Container Initiative image") + action.add_argument("--make-vagrant", action="store_true", + help="Build a Vagrant Box image") + + parser.add_argument("--iso", type=os.path.abspath, + help="Anaconda installation .iso path to use for qemu") + parser.add_argument("--iso-only", action="store_true", + help="Remove all iso creation artifacts except the boot.iso, " + "combine with --iso-name to rename the boot.iso") + parser.add_argument("--iso-name", default=None, + help="Name of output iso file for --iso-only. Default is boot.iso") + parser.add_argument("--ks", action="append", type=os.path.abspath, + help="Kickstart file defining the install.") + parser.add_argument("--image-only", action="store_true", + help="Exit after creating fs/disk image.") + + parser.add_argument("--no-virt", action="store_true", + help="Run anaconda directly on host instead of using qemu") + parser.add_argument("--proxy", + help="proxy URL to use for the install") + parser.add_argument("--anaconda-arg", action="append", dest="anaconda_args", + help="Additional argument to pass to anaconda (no-virt " + "mode). Pass once for each argument") + parser.add_argument("--armplatform", + help="the platform to use when creating images for ARM, " + "i.e., highbank, mvebu, omap, tegra, etc.") + parser.add_argument("--location", default=None, type=os.path.abspath, + help="location of iso directory tree with initrd.img " + "and vmlinuz. Used to run qemu with a newer initrd " + "than the iso.") + + parser.add_argument("--logfile", default="./livemedia.log", + type=os.path.abspath, + help="Name and path for primary logfile, other logs will " + "be created in the same directory.") + parser.add_argument("--lorax-templates", default=None, + type=os.path.abspath, + help="Path to mako templates for lorax") + parser.add_argument("--tmp", default="/var/tmp", type=os.path.abspath, + help="Top level temporary directory") + parser.add_argument("--resultdir", default=None, dest="result_dir", + type=os.path.abspath, + help="Directory to copy the resulting images and iso into. " + "Defaults to the temporary working directory") + + parser.add_argument("--macboot", action="store_true", default=True, + dest="domacboot") + parser.add_argument("--nomacboot", action="store_false", + dest="domacboot") + + parser.add_argument("--extra-boot-args", default="", dest="extra_boot_args", + help="Extra arguments to add to the bootloader kernel cmdline in the templates") + + image_group = parser.add_argument_group("disk/fs image arguments") + image_group.add_argument("--disk-image", type=os.path.abspath, + help="Path to existing disk image to use for creating final image.") + image_group.add_argument("--keep-image", action="store_true", + help="Keep raw disk image after .iso creation") + image_group.add_argument("--fs-image", type=os.path.abspath, + help="Path to existing filesystem image to use for creating final image.") + image_group.add_argument("--image-name", default=None, + help="Name of output file to create. Used for tar, fs and disk image. Default is a random name.") + image_group.add_argument("--tar-disk-name", default=None, + help="Name of the archive member for make-tar-disk.") + image_group.add_argument("--fs-label", default="Anaconda", + help="Label to set on fsimage, default is 'Anaconda'") + image_group.add_argument("--image-size-align", type=int, default=0, + help="Create a disk image with a size that is a multiple of this value in MiB.") + image_group.add_argument("--image-type", default=None, + help="Create an image with qemu-img. See qemu-img --help for supported formats.") + image_group.add_argument("--qemu-arg", action="append", dest="qemu_args", default=[], + help="Arguments to pass to qemu-img. Pass once for each argument, they will be used for ALL calls to qemu-img.") + image_group.add_argument("--qcow2", action="store_true", + help="Create qcow2 image instead of raw sparse image when making disk images.") + image_group.add_argument("--qcow2-arg", action="append", dest="qemu_args", default=[], + help="Arguments to pass to qemu-img. Pass once for each argument, they will be used for ALL calls to qemu-img.") + image_group.add_argument("--compression", default="xz", + help="Compression binary for make-tar. xz, lzma, gzip, and bzip2 are supported. xz is the default.") + image_group.add_argument("--compress-arg", action="append", dest="compress_args", default=[], + help="Arguments to pass to compression. Pass once for each argument") + # Group of arguments for appliance creation + app_group = parser.add_argument_group("appliance arguments") + app_group.add_argument("--app-name", default=None, + help="Name of appliance to pass to template") + app_group.add_argument("--app-template", default=None, + help="Path to template to use for appliance data.") + app_group.add_argument("--app-file", default="appliance.xml", + help="Appliance template results file.") + + # Group of arguments to pass to qemu + virt_group = parser.add_argument_group("qemu arguments") + virt_group.add_argument("--ram", metavar="MEMORY", type=int, default=2048, + help="Memory to allocate for installer in megabytes.") + virt_group.add_argument("--vcpus", type=int, default=None, + help="Passed to qemu -smp command") + virt_group.add_argument("--vnc", + help="Passed to qemu -display command. eg. vnc=127.0.0.1:5, default is to " + "choose the first unused vnc port.") + virt_group.add_argument("--arch", default=None, + help="System arch to build for. Used to select qemu-system-* command. " + "Defaults to qemu-system-<arch>") + virt_group.add_argument("--kernel-args", + help="Additional argument to pass to the installation kernel") + virt_group.add_argument("--ovmf-path", default="/usr/share/edk2/ovmf/", + help="Path to OVMF firmware") + virt_group.add_argument("--virt-uefi", action="store_true", default=False, + help="Use OVMF firmware to boot the VM in UEFI mode") + virt_group.add_argument("--no-kvm", action="store_true", default=False, + help="Skip using kvm with qemu even if it is available.") + virt_group.add_argument("--with-rng", default="/dev/random", + help="RNG device for QEMU (none for no RNG)") + + # dracut arguments + dracut_group = parser.add_argument_group("dracut arguments") + dracut_group.add_argument("--dracut-arg", action="append", dest="dracut_args", + help="Argument to pass to dracut when " + "rebuilding the initramfs. Pass this " + "once for each argument. NOTE: this " + "overrides the default. (default: %s)" % dracut_default) + + # pxe to live arguments + pxelive_group = parser.add_argument_group("pxe to live arguments") + pxelive_group.add_argument("--live-rootfs-size", type=int, default=0, + help="Size of root filesystem of live image in GiB") + pxelive_group.add_argument("--live-rootfs-keep-size", action="store_true", + help="Keep the original size of root filesystem in live image") + + # OCI specific commands + oci_group = parser.add_argument_group("OCI arguments") + oci_group.add_argument("--oci-config", + help="config.json OCI configuration file") + oci_group.add_argument("--oci-runtime", + help="runtime.json OCI configuration file") + + # Vagrant specific commands + vagrant_group = parser.add_argument_group("Vagrant arguments") + vagrant_group.add_argument("--vagrant-metadata", + help="optional metadata.json file") + vagrant_group.add_argument("--vagrantfile", + help="optional vagrantfile") + + parser.add_argument("--title", default="Linux Live Media", + help="Substituted for @TITLE@ in bootloader config files") + parser.add_argument("--project", default="Linux", + help="substituted for @PROJECT@ in bootloader config files") + parser.add_argument("--releasever", default="29", + help="substituted for @VERSION@ in bootloader config files") + parser.add_argument("--volid", default=None, help="volume id") + parser.add_argument("--squashfs_args", + help="additional squashfs args") + parser.add_argument("--timeout", default=None, type=int, + help="Cancel installer after X minutes") + + # add the show version option + parser.add_argument("-V", help="show program's version number and exit", + action="version", version=version) + + return parser
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/creator.html b/f29-branch/_modules/pylorax/creator.html new file mode 100644 index 00000000..56c908be --- /dev/null +++ b/f29-branch/_modules/pylorax/creator.html @@ -0,0 +1,994 @@ + + + + + + + + + + + pylorax.creator — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.creator

+#
+# Copyright (C) 2011-2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("pylorax")
+
+import os
+import tempfile
+import subprocess
+import shutil
+import hashlib
+import glob
+
+# Use Mako templates for appliance builder descriptions
+from mako.template import Template
+from mako.exceptions import text_error_template
+
+# Use pykickstart to calculate disk image size
+from pykickstart.parser import KickstartParser
+from pykickstart.constants import KS_SHUTDOWN
+from pykickstart.version import makeVersion
+
+# Use the Lorax treebuilder branch for iso creation
+from pylorax import ArchData
+from pylorax.base import DataHolder
+from pylorax.executils import execWithRedirect, runcmd
+from pylorax.imgutils import PartitionMount
+from pylorax.imgutils import mount, umount, Mount
+from pylorax.imgutils import mksquashfs, mkrootfsimg
+from pylorax.imgutils import copytree
+from pylorax.installer import novirt_install, virt_install, InstallError
+from pylorax.treebuilder import TreeBuilder, RuntimeBuilder
+from pylorax.treebuilder import findkernels
+from pylorax.sysutils import joinpaths, remove
+
+
+# Default parameters for rebuilding initramfs, override with --dracut-args
+DRACUT_DEFAULT = ["--xz", "--add", "livenet dmsquash-live convertfs pollcdrom qemu qemu-net",
+                  "--omit", "plymouth", "--no-hostonly", "--debug", "--no-early-microcode"]
+
+RUNTIME = "images/install.img"
+
+
[docs]class FakeDNF(object): + """ + A minimal DNF object suitable for passing to RuntimeBuilder + + lmc uses RuntimeBuilder to run the arch specific iso creation + templates, so the the installroot config value is the important part of + this. Everything else should be a nop. + """ + def __init__(self, conf): + self.conf = conf + +
[docs] def reset(self): + pass
+ +
[docs]def is_image_mounted(disk_img): + """ + Check to see if the disk_img is mounted + + :returns: True if disk_img is in /proc/mounts + :rtype: bool + """ + with open("/proc/mounts") as mounts: + for mnt in mounts: + fields = mnt.split() + if len(fields) > 2 and fields[1] == disk_img: + return True + return False
+ +
[docs]def find_ostree_root(phys_root): + """ + Find root of ostree deployment + + :param str phys_root: Path to physical root + :returns: Relative path of ostree deployment root + :rtype: str + :raise Exception: More than one deployment roots were found + """ + ostree_root = "" + ostree_sysroots = glob.glob(joinpaths(phys_root, "ostree/boot.?/*/*/0")) + log.debug("ostree_sysroots = %s", ostree_sysroots) + if ostree_sysroots: + if len(ostree_sysroots) > 1: + raise Exception("Too many deployment roots found: %s" % ostree_sysroots) + ostree_root = os.path.relpath(ostree_sysroots[0], phys_root) + return ostree_root
+ +
[docs]def get_arch(mount_dir): + """ + Get the kernel arch + + :returns: Arch of first kernel found at mount_dir/boot/ or i386 + :rtype: str + """ + kernels = findkernels(mount_dir) + if not kernels: + return "i386" + return kernels[0].arch
+ +
[docs]def squashfs_args(opts): + """ Returns the compression type and args to use when making squashfs + + :param opts: ArgumentParser object with compression and compressopts + :returns: tuple of compression type and args + :rtype: tuple + """ + compression = opts.compression or "xz" + arch = ArchData(opts.arch or os.uname().machine) + if compression == "xz" and arch.bcj: + compressargs = ["-Xbcj", arch.bcj] + else: + compressargs = [] + return (compression, compressargs)
+ + +
[docs]def make_appliance(disk_img, name, template, outfile, networks=None, ram=1024, + vcpus=1, arch=None, title="Linux", project="Linux", + releasever="29"): + """ + Generate an appliance description file + + :param str disk_img: Full path of the disk image + :param str name: Name of the appliance, passed to the template + :param str template: Full path of Mako template + :param str outfile: Full path of file to write, using template + :param list networks: List of networks(str) from the kickstart + :param int ram: Ram, in MiB, passed to template. Default is 1024 + :param int vcpus: CPUs, passed to template. Default is 1 + :param str arch: CPU architecture. Default is 'x86_64' + :param str title: Title, passed to template. Default is 'Linux' + :param str project: Project, passed to template. Default is 'Linux' + :param str releasever: Release version, passed to template. Default is 29 + """ + if not (disk_img and template and outfile): + return None + + log.info("Creating appliance definition using %s", template) + + if not arch: + arch = "x86_64" + + log.info("Calculating SHA256 checksum of %s", disk_img) + sha256 = hashlib.sha256() + with open(disk_img, "rb") as f: + while True: + data = f.read(1024**2) + if not data: + break + sha256.update(data) + log.info("SHA256 of %s is %s", disk_img, sha256.hexdigest()) + disk_info = DataHolder(name=os.path.basename(disk_img), format="raw", + checksum_type="sha256", checksum=sha256.hexdigest()) + try: + result = Template(filename=template).render(disks=[disk_info], name=name, + arch=arch, memory=ram, vcpus=vcpus, networks=networks, + title=title, project=project, releasever=releasever) + except Exception: + log.error(text_error_template().render()) + raise + + with open(outfile, "w") as f: + f.write(result)
+ + +
[docs]def make_runtime(opts, mount_dir, work_dir, size=None): + """ + Make the squashfs image from a directory + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str mount_dir: Directory tree to compress + :param str work_dir: Output compressed image to work_dir+images/install.img + :param int size: Size of disk image, in GiB + """ + kernel_arch = get_arch(mount_dir) + + # Fake dnf object + fake_dbo = FakeDNF(conf=DataHolder(installroot=mount_dir)) + # Fake arch with only basearch set + arch = ArchData(kernel_arch) + # TODO: Need to get release info from someplace... + product = DataHolder(name=opts.project, version=opts.releasever, release="", + variant="", bugurl="", isfinal=False) + + # This is a mounted image partition, cannot hardlink to it, so just use it + # symlink mount_dir/images to work_dir/images so we don't run out of space + os.makedirs(joinpaths(work_dir, "images")) + + rb = RuntimeBuilder(product, arch, fake_dbo) + compression, compressargs = squashfs_args(opts) + log.info("Creating runtime") + rb.create_ext4_runtime(joinpaths(work_dir, RUNTIME), size=size, + compression=compression, compressargs=compressargs)
+ + +
[docs]def rebuild_initrds_for_live(opts, sys_root_dir, results_dir): + """ + Rebuild intrds for pxe live image (root=live:http://) + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str sys_root_dir: Path to root of the system + :param str results_dir: Path of directory for storing results + """ + if not opts.dracut_args: + dracut_args = DRACUT_DEFAULT + else: + dracut_args = [] + for arg in opts.dracut_args: + dracut_args += arg.split(" ", 1) + log.info("dracut args = %s", dracut_args) + + dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + dracut_args + + kdir = "boot" + if opts.ostree: + kernels_dir = glob.glob(joinpaths(sys_root_dir, "boot/ostree/*")) + if kernels_dir: + kdir = os.path.relpath(kernels_dir[0], sys_root_dir) + + kernels = [kernel for kernel in findkernels(sys_root_dir, kdir)] + if not kernels: + raise Exception("No initrds found, cannot rebuild_initrds") + + # Hush some dracut warnings. TODO: bind-mount proc in place? + open(joinpaths(sys_root_dir,"/proc/modules"),"w") + + if opts.ostree: + # Dracut assumes to have some dirs in disk image + # /var/tmp for temp files + vartmp_dir = joinpaths(sys_root_dir, "var/tmp") + if not os.path.isdir(vartmp_dir): + os.mkdir(vartmp_dir) + # /root (maybe not fatal) + root_dir = joinpaths(sys_root_dir, "var/roothome") + if not os.path.isdir(root_dir): + os.mkdir(root_dir) + # /tmp (maybe not fatal) + tmp_dir = joinpaths(sys_root_dir, "sysroot/tmp") + if not os.path.isdir(tmp_dir): + os.mkdir(tmp_dir) + + # Write the new initramfs directly to the results directory + os.mkdir(joinpaths(sys_root_dir, "results")) + mount(results_dir, opts="bind", mnt=joinpaths(sys_root_dir, "results")) + # Dracut runs out of space inside the minimal rootfs image + mount("/var/tmp", opts="bind", mnt=joinpaths(sys_root_dir, "var/tmp")) + for kernel in kernels: + if hasattr(kernel, "initrd"): + outfile = os.path.basename(kernel.initrd.path) + else: + # Construct an initrd from the kernel name + outfile = os.path.basename(kernel.path.replace("vmlinuz-", "initrd-") + ".img") + log.info("rebuilding %s", outfile) + + kver = kernel.version + + cmd = dracut + ["/results/"+outfile, kver] + runcmd(cmd, root=sys_root_dir) + + shutil.copy2(joinpaths(sys_root_dir, kernel.path), results_dir) + umount(joinpaths(sys_root_dir, "var/tmp"), delete=False) + umount(joinpaths(sys_root_dir, "results"), delete=False) + os.unlink(joinpaths(sys_root_dir,"/proc/modules"))
+ +
[docs]def create_pxe_config(template, images_dir, live_image_name, add_args = None): + """ + Create template for pxe to live configuration + + :param str images_dir: Path of directory with images to be used + :param str live_image_name: Name of live rootfs image file + :param list add_args: Arguments to be added to initrd= pxe config + """ + + add_args = add_args or [] + + kernels = [kernel for kernel in findkernels(images_dir, kdir="") + if hasattr(kernel, "initrd")] + if not kernels: + return + + kernel = kernels[0] + + add_args_str = " ".join(add_args) + + + try: + result = Template(filename=template).render(kernel=kernel.path, + initrd=kernel.initrd.path, liveimg=live_image_name, + addargs=add_args_str) + except Exception: + log.error(text_error_template().render()) + raise + + with open (joinpaths(images_dir, "PXE_CONFIG"), "w") as f: + f.write(result)
+ + +
[docs]def make_livecd(opts, mount_dir, work_dir): + """ + Take the content from the disk image and make a livecd out of it + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str mount_dir: Directory tree to compress + :param str work_dir: Output compressed image to work_dir+images/install.img + + This uses wwood's squashfs live initramfs method: + * put the real / into LiveOS/rootfs.img + * make a squashfs of the LiveOS/rootfs.img tree + * This is loaded by dracut when the cmdline is passed to the kernel: + root=live:CDLABEL=<volid> rd.live.image + """ + kernel_arch = get_arch(mount_dir) + + arch = ArchData(kernel_arch) + # TODO: Need to get release info from someplace... + product = DataHolder(name=opts.project, version=opts.releasever, release="", + variant="", bugurl="", isfinal=False) + + # Link /images to work_dir/images to make the templates happy + if os.path.islink(joinpaths(mount_dir, "images")): + os.unlink(joinpaths(mount_dir, "images")) + execWithRedirect("/bin/ln", ["-s", joinpaths(work_dir, "images"), + joinpaths(mount_dir, "images")]) + + # The templates expect the config files to be in /tmp/config_files + # I think these should be release specific, not from lorax, but for now + configdir = joinpaths(opts.lorax_templates,"live/config_files/") + configdir_path = "tmp/config_files" + fullpath = joinpaths(mount_dir, configdir_path) + if os.path.exists(fullpath): + remove(fullpath) + copytree(configdir, fullpath) + + isolabel = opts.volid or "{0.name}-{0.version}-{1.basearch}".format(product, arch) + if len(isolabel) > 32: + isolabel = isolabel[:32] + log.warning("Truncating isolabel to 32 chars: %s", isolabel) + + tb = TreeBuilder(product=product, arch=arch, domacboot=opts.domacboot, + inroot=mount_dir, outroot=work_dir, + runtime=RUNTIME, isolabel=isolabel, + templatedir=joinpaths(opts.lorax_templates,"live/"), + extra_boot_args=opts.extra_boot_args) + log.info("Rebuilding initrds") + if not opts.dracut_args: + dracut_args = DRACUT_DEFAULT + else: + dracut_args = [] + for arg in opts.dracut_args: + dracut_args += arg.split(" ", 1) + log.info("dracut args = %s", dracut_args) + tb.rebuild_initrds(add_args=dracut_args) + log.info("Building boot.iso") + tb.build() + + return work_dir
+ +
[docs]def mount_boot_part_over_root(img_mount): + """ + Mount boot partition to /boot of root fs mounted in img_mount + + Used for OSTree so it finds deployment configurations on live rootfs + + param img_mount: object with mounted disk image root partition + type img_mount: imgutils.PartitionMount + """ + root_dir = img_mount.mount_dir + is_boot_part = lambda dir: os.path.exists(dir+"/loader.0") + tmp_mount_dir = tempfile.mkdtemp(prefix="lmc-tmpdir-") + sysroot_boot_dir = None + for dev, _size in img_mount.loop_devices: + if dev is img_mount.mount_dev: + continue + try: + mount("/dev/mapper/"+dev, mnt=tmp_mount_dir) + if is_boot_part(tmp_mount_dir): + umount(tmp_mount_dir) + sysroot_boot_dir = joinpaths(root_dir, "boot") + mount("/dev/mapper/"+dev, mnt=sysroot_boot_dir) + break + else: + umount(tmp_mount_dir) + except subprocess.CalledProcessError as e: + log.debug("Looking for boot partition error: %s", e) + remove(tmp_mount_dir) + return sysroot_boot_dir
+ +
[docs]def make_squashfs(opts, disk_img, work_dir): + """ + Create a squashfs image of an unpartitioned filesystem disk image + + :param str disk_img: Path to the unpartitioned filesystem disk image + :param str work_dir: Output compressed image to work_dir+images/install.img + :param str compression: Compression type to use + :returns: True if squashfs creation was successful. False if there was an error. + :rtype: bool + + Take disk_img and put it into LiveOS/rootfs.img and squashfs this + tree into work_dir+images/install.img + + fsck.ext4 is run on the disk image to make sure there are no errors and to zero + out any deleted blocks to make it compress better. If this fails for any reason + it will return False and log the error. + """ + # Make sure free blocks are actually zeroed so it will compress + rc = execWithRedirect("/usr/sbin/fsck.ext4", ["-y", "-f", "-E", "discard", disk_img]) + if rc != 0: + log.error("Problem zeroing free blocks of %s", disk_img) + return False + + liveos_dir = joinpaths(work_dir, "runtime/LiveOS") + os.makedirs(liveos_dir) + os.makedirs(os.path.dirname(joinpaths(work_dir, RUNTIME))) + + rc = execWithRedirect("/bin/ln", [disk_img, joinpaths(liveos_dir, "rootfs.img")]) + if rc != 0: + shutil.copy2(disk_img, joinpaths(liveos_dir, "rootfs.img")) + + compression, compressargs = squashfs_args(opts) + mksquashfs(joinpaths(work_dir, "runtime"), + joinpaths(work_dir, RUNTIME), compression, compressargs) + remove(joinpaths(work_dir, "runtime")) + return True
+ +
[docs]def calculate_disk_size(opts, ks): + """ Calculate the disk size from the kickstart + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str ks: Path to the kickstart to use for the installation + :returns: Disk size in MiB + :rtype: int + + Also takes into account the use of reqpart or reqpart --add-boot + """ + # Disk size for a filesystem image should only be the size of / + # to prevent surprises when using the same kickstart for different installations. + unique_partitions = dict((p.mountpoint, p) for p in ks.handler.partition.partitions) + if opts.no_virt and (opts.make_iso or opts.make_fsimage): + disk_size = 2 + sum(p.size for p in unique_partitions.values() if p.mountpoint == "/") + else: + disk_size = 2 + sum(p.size for p in unique_partitions.values()) + + # reqpart can add 1M, 2M, 200M based on platform. Add 500M to be sure + if ks.handler.reqpart.seen: + log.info("Adding 500M for reqpart") + disk_size += 500 + + # It can also request adding /boot which is 1G + if ks.handler.reqpart.addBoot: + log.info("Adding 1024M for reqpart --addboot") + disk_size += 1024 + + if opts.image_size_align: + disk_size += opts.image_size_align - (disk_size % opts.image_size_align) + + log.info("Using disk size of %sMiB", disk_size) + return disk_size
+ +
[docs]def make_image(opts, ks, cancel_func=None): + """ + Install to a disk image + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str ks: Path to the kickstart to use for the installation + :param cancel_func: Function that returns True to cancel build + :type cancel_func: function + :returns: Path of the image created + :rtype: str + + Use qemu+boot.iso or anaconda to install to a disk image. + """ + + # For make_tar_disk, opts.image_name is the name of the final tarball. + # Use opts.tar_disk_name as the name of the disk image + if opts.make_tar_disk: + disk_img = joinpaths(opts.result_dir, opts.tar_disk_name) + elif opts.image_name: + disk_img = joinpaths(opts.result_dir, opts.image_name) + else: + disk_img = tempfile.mktemp(prefix="lmc-disk-", suffix=".img", dir=opts.result_dir) + log.info("disk_img = %s", disk_img) + disk_size = calculate_disk_size(opts, ks) + + # For make_tar_disk, pass a second path parameter for the final tarball + # not the final output file. + if opts.make_tar_disk: + tar_img = joinpaths(opts.result_dir, opts.image_name) + else: + tar_img = None + + try: + if opts.no_virt: + novirt_install(opts, disk_img, disk_size, cancel_func=cancel_func, tar_img=tar_img) + else: + install_log = os.path.abspath(os.path.dirname(opts.logfile))+"/virt-install.log" + log.info("install_log = %s", install_log) + + virt_install(opts, install_log, disk_img, disk_size, cancel_func=cancel_func, tar_img=tar_img) + except InstallError as e: + log.error("Install failed: %s", e) + if not opts.keep_image: + if os.path.exists(disk_img): + log.info("Removing bad disk image") + os.unlink(disk_img) + if tar_img and os.path.exists(tar_img): + log.info("Removing bad tar file") + os.unlink(tar_img) + raise + + log.info("Disk Image install successful") + + if opts.make_tar_disk: + return tar_img + + return disk_img
+ + +
[docs]def make_live_images(opts, work_dir, disk_img): + """ + Create live images from direcory or rootfs image + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str work_dir: Directory for storing results + :param str disk_img: Path to disk image (fsimage or partitioned) + :returns: Path of directory with created images or None + :rtype: str + + fsck.ext4 is run on the rootfs_image to make sure there are no errors and to zero + out any deleted blocks to make it compress better. If this fails for any reason + it will return None and log the error. + """ + sys_root = "" + + squashfs_root_dir = joinpaths(work_dir, "squashfs_root") + liveos_dir = joinpaths(squashfs_root_dir, "LiveOS") + os.makedirs(liveos_dir) + rootfs_img = joinpaths(liveos_dir, "rootfs.img") + + if opts.fs_image or opts.no_virt: + # Find the ostree root in the fsimage + if opts.ostree: + with Mount(disk_img, opts="loop") as mnt_dir: + sys_root = find_ostree_root(mnt_dir) + + # Try to hardlink the image, if that fails, copy it + rc = execWithRedirect("/bin/ln", [disk_img, rootfs_img]) + if rc != 0: + shutil.copy2(disk_img, rootfs_img) + else: + is_root_part = None + if opts.ostree: + is_root_part = lambda dir: os.path.exists(dir+"/ostree/deploy") + with PartitionMount(disk_img, mount_ok=is_root_part) as img_mount: + if img_mount and img_mount.mount_dir: + try: + mounted_sysroot_boot_dir = None + if opts.ostree: + sys_root = find_ostree_root(img_mount.mount_dir) + mounted_sysroot_boot_dir = mount_boot_part_over_root(img_mount) + if opts.live_rootfs_keep_size: + size = img_mount.mount_size / 1024**3 + else: + size = opts.live_rootfs_size or None + log.info("Creating live rootfs image") + mkrootfsimg(img_mount.mount_dir, rootfs_img, "LiveOS", size=size, sysroot=sys_root) + finally: + if mounted_sysroot_boot_dir: + umount(mounted_sysroot_boot_dir) + log.debug("sys_root = %s", sys_root) + + # Make sure free blocks are actually zeroed so it will compress + rc = execWithRedirect("/usr/sbin/fsck.ext4", ["-y", "-f", "-E", "discard", rootfs_img]) + if rc != 0: + log.error("Problem zeroing free blocks of %s", disk_img) + return None + + log.info("Packing live rootfs image") + add_pxe_args = [] + live_image_name = "live-rootfs.squashfs.img" + compression, compressargs = squashfs_args(opts) + mksquashfs(squashfs_root_dir, joinpaths(work_dir, live_image_name), compression, compressargs) + + log.info("Rebuilding initramfs for live") + with Mount(rootfs_img, opts="loop") as mnt_dir: + try: + mount(joinpaths(mnt_dir, "boot"), opts="bind", mnt=joinpaths(mnt_dir, sys_root, "boot")) + rebuild_initrds_for_live(opts, joinpaths(mnt_dir, sys_root), work_dir) + finally: + umount(joinpaths(mnt_dir, sys_root, "boot"), delete=False) + + remove(squashfs_root_dir) + + if opts.ostree: + add_pxe_args.append("ostree=/%s" % sys_root) + template = joinpaths(opts.lorax_templates, "pxe-live/pxe-config.tmpl") + create_pxe_config(template, work_dir, live_image_name, add_pxe_args) + + return work_dir
+ +
[docs]def check_kickstart(ks, opts): + """Check the parsed kickstart object for errors + + :param ks: Parsed Kickstart object + :type ks: pykickstart.parser.KickstartParser + :param opts: Commandline options to control the process + :type opts: Either a DataHolder or ArgumentParser + :returns: List of error strings or empty list + :rtype: list + """ + errors = [] + if opts.no_virt and ks.handler.method.method not in ("url", "nfs") \ + and not ks.handler.ostreesetup.seen: + errors.append("Only url, nfs and ostreesetup install methods are currently supported." + "Please fix your kickstart file." ) + + if ks.handler.repo.seen and ks.handler.method.method != "url": + errors.append("repo can only be used with the url install method. Add url to your " + "kickstart file.") + + if ks.handler.method.method in ("url", "nfs") and not ks.handler.network.seen: + errors.append("The kickstart must activate networking if " + "the url or nfs install method is used.") + + if ks.handler.displaymode.displayMode is not None: + errors.append("The kickstart must not set a display mode (text, cmdline, " + "graphical), this will interfere with livemedia-creator.") + + if opts.make_fsimage or (opts.make_pxe_live and opts.no_virt): + # Make sure the kickstart isn't using autopart and only has a / mountpoint + part_ok = not any(p for p in ks.handler.partition.partitions + if p.mountpoint not in ["/", "swap"]) + if not part_ok or ks.handler.autopart.seen: + errors.append("Filesystem images must use a single / part, not autopart or " + "multiple partitions. swap is allowed but not used.") + + if not opts.no_virt and ks.handler.reboot.action != KS_SHUTDOWN: + errors.append("The kickstart must include shutdown when using virt installation.") + + return errors
+ +
[docs]def run_creator(opts, cancel_func=None): + """Run the image creator process + + :param opts: Commandline options to control the process + :type opts: Either a DataHolder or ArgumentParser + :param cancel_func: Function that returns True to cancel build + :type cancel_func: function + :returns: The result directory and the disk image path. + :rtype: Tuple of str + + This function takes the opts arguments and creates the selected output image. + See the cmdline --help for livemedia-creator for the possible options + + (Yes, this is not ideal, but we can fix that later) + """ + result_dir = None + + # Parse the kickstart + if opts.ks: + ks_version = makeVersion() + ks = KickstartParser(ks_version, errorsAreFatal=False, missingIncludeIsFatal=False) + ks.readKickstart(opts.ks[0]) + + # live iso usually needs dracut-live so warn the user if it is missing + if opts.ks and opts.make_iso: + if "dracut-live" not in ks.handler.packages.packageList: + log.error("dracut-live package is missing from the kickstart.") + raise RuntimeError("dracut-live package is missing from the kickstart.") + + # Make the disk or filesystem image + if not opts.disk_image and not opts.fs_image: + if not opts.ks: + raise RuntimeError("Image creation requires a kickstart file") + + # Check the kickstart for problems + errors = check_kickstart(ks, opts) + if errors: + list(log.error(e) for e in errors) + raise RuntimeError("\n".join(errors)) + + # Make the image. Output of this is either a partitioned disk image or a fsimage + try: + disk_img = make_image(opts, ks, cancel_func=cancel_func) + except InstallError as e: + log.error("ERROR: Image creation failed: %s", e) + raise RuntimeError("Image creation failed: %s" % e) + + if opts.image_only: + return (result_dir, disk_img) + + if opts.make_iso: + work_dir = tempfile.mkdtemp(prefix="lmc-work-") + log.info("working dir is %s", work_dir) + + if (opts.fs_image or opts.no_virt) and not opts.disk_image: + # Create iso from a filesystem image + disk_img = opts.fs_image or disk_img + + if not make_squashfs(opts, disk_img, work_dir): + log.error("squashfs.img creation failed") + raise RuntimeError("squashfs.img creation failed") + + if cancel_func and cancel_func(): + raise RuntimeError("ISO creation canceled") + + with Mount(disk_img, opts="loop") as mount_dir: + result_dir = make_livecd(opts, mount_dir, work_dir) + else: + # Create iso from a partitioned disk image + disk_img = opts.disk_image or disk_img + with PartitionMount(disk_img) as img_mount: + if img_mount and img_mount.mount_dir: + make_runtime(opts, img_mount.mount_dir, work_dir, calculate_disk_size(opts, ks)/1024.0) + result_dir = make_livecd(opts, img_mount.mount_dir, work_dir) + + # --iso-only removes the extra build artifacts, keeping only the boot.iso + if opts.iso_only and result_dir: + boot_iso = joinpaths(result_dir, "images/boot.iso") + if not os.path.exists(boot_iso): + log.error("%s is missing, skipping --iso-only.", boot_iso) + else: + iso_dir = tempfile.mkdtemp(prefix="lmc-result-") + dest_file = joinpaths(iso_dir, opts.iso_name or "boot.iso") + shutil.move(boot_iso, dest_file) + shutil.rmtree(result_dir) + result_dir = iso_dir + + # cleanup the mess + # cleanup work_dir? + if disk_img and not (opts.keep_image or opts.disk_image or opts.fs_image): + os.unlink(disk_img) + log.info("Disk image erased") + disk_img = None + elif opts.make_appliance: + if not opts.ks: + networks = [] + else: + networks = ks.handler.network.network + make_appliance(opts.disk_image or disk_img, opts.app_name, + opts.app_template, opts.app_file, networks, opts.ram, + opts.vcpus or 1, opts.arch, opts.title, opts.project, opts.releasever) + elif opts.make_pxe_live: + work_dir = tempfile.mkdtemp(prefix="lmc-work-") + log.info("working dir is %s", work_dir) + disk_img = opts.fs_image or opts.disk_image or disk_img + log.debug("disk image is %s", disk_img) + + result_dir = make_live_images(opts, work_dir, disk_img) + if result_dir is None: + log.error("Creating PXE live image failed.") + raise RuntimeError("Creating PXE live image failed.") + + if opts.result_dir != opts.tmp and result_dir: + copytree(result_dir, opts.result_dir, preserve=False) + shutil.rmtree(result_dir) + result_dir = None + + return (result_dir, disk_img)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/decorators.html b/f29-branch/_modules/pylorax/decorators.html new file mode 100644 index 00000000..cb420856 --- /dev/null +++ b/f29-branch/_modules/pylorax/decorators.html @@ -0,0 +1,247 @@ + + + + + + + + + + + pylorax.decorators — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.decorators

+#
+# decorators.py
+#
+# Copyright (C) 2009-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#
+
+
[docs]def singleton(cls): + instances = {} + + def get_instance(): + if cls not in instances: + instances[cls] = cls() + return instances[cls] + + return get_instance
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/discinfo.html b/f29-branch/_modules/pylorax/discinfo.html new file mode 100644 index 00000000..e84b6520 --- /dev/null +++ b/f29-branch/_modules/pylorax/discinfo.html @@ -0,0 +1,262 @@ + + + + + + + + + + + pylorax.discinfo — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.discinfo

+#
+# discinfo.py
+#
+# Copyright (C) 2010-2015  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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#
+
+import logging
+logger = logging.getLogger("pylorax.discinfo")
+
+import os
+import time
+
+
+
[docs]class DiscInfo(object): + + def __init__(self, release, basearch): + self.release = release + self.basearch = basearch + +
[docs] def write(self, outfile): + if 'SOURCE_DATE_EPOCH' in os.environ: + timestamp = int(os.environ['SOURCE_DATE_EPOCH']) + else: + timestamp = time.time() + + logger.info("writing .discinfo file") + with open(outfile, "w") as fobj: + fobj.write("{0:f}\n".format(timestamp)) + fobj.write("{0.release}\n".format(self)) + fobj.write("{0.basearch}\n".format(self))
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/dnfbase.html b/f29-branch/_modules/pylorax/dnfbase.html new file mode 100644 index 00000000..ea842c31 --- /dev/null +++ b/f29-branch/_modules/pylorax/dnfbase.html @@ -0,0 +1,402 @@ + + + + + + + + + + + pylorax.dnfbase — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.dnfbase

+# Copyright (C) 2018 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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("pylorax")
+
+import dnf
+import os
+import shutil
+
+from pylorax import DEFAULT_PLATFORM_ID
+from pylorax.sysutils import flatconfig
+
+
[docs]def get_dnf_base_object(installroot, sources, mirrorlists=None, repos=None, + enablerepos=None, disablerepos=None, + tempdir="/var/tmp", proxy=None, releasever="29", + cachedir=None, logdir=None, sslverify=True, dnfplugins=None): + """ Create a dnf Base object and setup the repositories and installroot + + :param string installroot: Full path to the installroot + :param list sources: List of source repo urls to use for the installation + :param list enablerepos: List of repo names to enable + :param list disablerepos: List of repo names to disable + :param list mirrorlist: List of mirrors to use + :param string tempdir: Path of temporary directory + :param string proxy: http proxy to use when fetching packages + :param string releasever: Release version to pass to dnf + :param string cachedir: Directory to use for caching packages + :param bool noverifyssl: Set to True to ignore the CA of ssl certs. eg. use self-signed ssl for https repos. + + If tempdir is not set /var/tmp is used. + If cachedir is None a dnf.cache directory is created inside tmpdir + """ + def sanitize_repo(repo): + """Convert bare paths to file:/// URIs, and silently reject protocols unhandled by yum""" + if repo.startswith("/"): + return "file://{0}".format(repo) + elif any(repo.startswith(p) for p in ('http://', 'https://', 'ftp://', 'file://')): + return repo + else: + return None + + mirrorlists = mirrorlists or [] + + # sanitize the repositories + sources = list(sanitize_repo(r) for r in sources) + mirrorlists = list(sanitize_repo(r) for r in mirrorlists) + + # remove invalid repositories + sources = list(r for r in sources if r) + mirrorlists = list(r for r in mirrorlists if r) + + if not cachedir: + cachedir = os.path.join(tempdir, "dnf.cache") + if not os.path.isdir(cachedir): + os.mkdir(cachedir) + + if not logdir: + logdir = os.path.join(tempdir, "dnf.logs") + if not os.path.isdir(logdir): + os.mkdir(logdir) + + dnfbase = dnf.Base() + # Enable DNF pluings + # NOTE: These come from the HOST system's environment + if dnfplugins: + if dnfplugins[0] == "*": + # Enable them all + dnfbase.init_plugins() + else: + # Only enable the listed plugins + dnfbase.init_plugins(disabled_glob=["*"], enable_plugins=dnfplugins) + conf = dnfbase.conf + conf.logdir = logdir + conf.cachedir = cachedir + + conf.install_weak_deps = False + conf.releasever = releasever + conf.installroot = installroot + conf.prepend_installroot('persistdir') + # this is a weird 'AppendOption' thing that, when you set it, + # actually appends. Doing this adds 'nodocs' to the existing list + # of values, over in libdnf, it does not replace the existing values. + conf.tsflags = ['nodocs'] + + if proxy: + conf.proxy = proxy + + if sslverify == False: + conf.sslverify = False + + # DNF 3.2 needs to have module_platform_id set, otherwise depsolve won't work correctly + if not os.path.exists("/etc/os-release"): + log.warning("/etc/os-release is missing, cannot determine platform id, falling back to %s", DEFAULT_PLATFORM_ID) + platform_id = DEFAULT_PLATFORM_ID + else: + os_release = flatconfig("/etc/os-release") + platform_id = os_release.get("PLATFORM_ID", DEFAULT_PLATFORM_ID) + log.info("Using %s for module_platform_id", platform_id) + conf.module_platform_id = platform_id + + # Add .repo files + if repos: + reposdir = os.path.join(tempdir, "dnf.repos") + if not os.path.isdir(reposdir): + os.mkdir(reposdir) + for r in repos: + shutil.copy2(r, reposdir) + conf.reposdir = [reposdir] + dnfbase.read_all_repos() + + # add the sources + for i, r in enumerate(sources): + if "SRPM" in r or "srpm" in r: + log.info("Skipping source repo: %s", r) + continue + repo_name = "lorax-repo-%d" % i + repo = dnf.repo.Repo(repo_name, conf) + repo.baseurl = [r] + if proxy: + repo.proxy = proxy + repo.enable() + dnfbase.repos.add(repo) + log.info("Added '%s': %s", repo_name, r) + log.info("Fetching metadata...") + try: + repo.load() + except dnf.exceptions.RepoError as e: + log.error("Error fetching metadata for %s: %s", repo_name, e) + return None + + # add the mirrorlists + for i, r in enumerate(mirrorlists): + if "SRPM" in r or "srpm" in r: + log.info("Skipping source repo: %s", r) + continue + repo_name = "lorax-mirrorlist-%d" % i + repo = dnf.repo.Repo(repo_name, conf) + repo.mirrorlist = r + if proxy: + repo.proxy = proxy + repo.enable() + dnfbase.repos.add(repo) + log.info("Added '%s': %s", repo_name, r) + log.info("Fetching metadata...") + try: + repo.load() + except dnf.exceptions.RepoError as e: + log.error("Error fetching metadata for %s: %s", repo_name, e) + return None + + # Enable repos listed on the cmdline + for r in enablerepos: + repolist = dnfbase.repos.get_matching(r) + if not repolist: + log.warning("%s is an unknown repo, not enabling it", r) + else: + repolist.enable() + log.info("Enabled repo %s", r) + + # Disable repos listed on the cmdline + for r in disablerepos: + repolist = dnfbase.repos.get_matching(r) + if not repolist: + log.warning("%s is an unknown repo, not disabling it", r) + else: + repolist.disable() + log.info("Disabled repo %s", r) + + dnfbase.fill_sack(load_system_repo=False) + dnfbase.read_comps() + + return dnfbase
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/dnfhelper.html b/f29-branch/_modules/pylorax/dnfhelper.html new file mode 100644 index 00000000..883e5ef0 --- /dev/null +++ b/f29-branch/_modules/pylorax/dnfhelper.html @@ -0,0 +1,327 @@ + + + + + + + + + + + pylorax.dnfhelper — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.dnfhelper

+#
+# dnfhelper.py
+#
+# Copyright (C) 2010-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#                     Brian C. Lane <bcl@redhat.com>
+#
+
+import logging
+logger = logging.getLogger("pylorax.dnfhelper")
+import dnf
+import dnf.transaction
+import collections
+import time
+import pylorax.output as output
+
+__all__ = ['LoraxDownloadCallback', 'LoraxRpmCallback']
+
+def _paced(fn):
+    """Execute `fn` no more often then every 2 seconds."""
+    def paced_fn(self, *args):
+        now = time.time()
+        if now - self.last_time < 2:
+            return
+        self.last_time = now
+        return fn(self, *args)
+    return paced_fn
+
+
+
[docs]class LoraxDownloadCallback(dnf.callback.DownloadProgress): + def __init__(self): + self.downloads = collections.defaultdict(int) + self.last_time = time.time() + self.total_files = 0 + self.total_size = 0 + + self.pkgno = 0 + self.total = 0 + + self.output = output.LoraxOutput() + + @_paced + def _update(self): + msg = "Downloading %(pkgno)s / %(total_files)s RPMs, " \ + "%(downloaded)s / %(total_size)s (%(percent)d%%) done.\n" + downloaded = sum(self.downloads.values()) + vals = { + 'downloaded' : downloaded, + 'percent' : int(100 * downloaded/self.total_size), + 'pkgno' : self.pkgno, + 'total_files' : self.total_files, + 'total_size' : self.total_size + } + self.output.write(msg % vals) + +
[docs] def end(self, payload, status, msg): + nevra = str(payload) + if status is dnf.callback.STATUS_OK: + self.downloads[nevra] = payload.download_size + self.pkgno += 1 + self._update() + return + logger.critical("Failed to download '%s': %d - %s", nevra, status, msg)
+ +
[docs] def progress(self, payload, done): + nevra = str(payload) + self.downloads[nevra] = done + self._update()
+ + # dnf 2.5.0 adds a new argument, accept it if it is passed + # pylint: disable=arguments-differ +
[docs] def start(self, total_files, total_size, total_drpms=0): + self.total_files = total_files + self.total_size = total_size
+ + +
[docs]class LoraxRpmCallback(dnf.callback.TransactionProgress): + def __init__(self): + super(LoraxRpmCallback, self).__init__() + self._last_ts = None + +
[docs] def progress(self, package, action, ti_done, ti_total, ts_done, ts_total): + if action == dnf.transaction.PKG_INSTALL: + # do not report same package twice + if self._last_ts == ts_done: + return + self._last_ts = ts_done + + msg = '(%d/%d) %s' % (ts_done, ts_total, package) + logger.info(msg) + elif action == dnf.transaction.TRANS_POST: + msg = "Performing post-installation setup tasks" + logger.info(msg)
+ +
[docs] def error(self, message): + logger.warning(message)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/executils.html b/f29-branch/_modules/pylorax/executils.html new file mode 100644 index 00000000..03c40eec --- /dev/null +++ b/f29-branch/_modules/pylorax/executils.html @@ -0,0 +1,566 @@ + + + + + + + + + + + pylorax.executils — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.executils

+#
+# executil.py - subprocess execution utility functions
+#
+# Copyright (C) 1999-2015
+# Red Hat, Inc.  All rights reserved.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+#
+
+import os
+import subprocess
+from subprocess import TimeoutExpired
+import signal
+
+import logging
+log = logging.getLogger("pylorax")
+program_log = logging.getLogger("program")
+
+# pylint: disable=not-context-manager
+from threading import Lock
+program_log_lock = Lock()
+
+_child_env = {}
+
+
[docs]def setenv(name, value): + """ Set an environment variable to be used by child processes. + + This method does not modify os.environ for the running process, which + is not thread-safe. If setenv has already been called for a particular + variable name, the old value is overwritten. + + :param str name: The name of the environment variable + :param str value: The value of the environment variable + """ + + _child_env[name] = value
+ +
[docs]def augmentEnv(): + env = os.environ.copy() + env.update(_child_env) + return env
+ +
[docs]class ExecProduct(object): + def __init__(self, rc, stdout, stderr): + self.rc = rc + self.stdout = stdout + self.stderr = stderr
+ +
[docs]def startProgram(argv, root='/', stdin=None, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + env_prune=None, env_add=None, reset_handlers=True, reset_lang=True, **kwargs): + """ Start an external program and return the Popen object. + + The root and reset_handlers arguments are handled by passing a + preexec_fn argument to subprocess.Popen, but an additional preexec_fn + can still be specified and will be run. The user preexec_fn will be run + last. + + :param argv: The command to run and argument + :param root: The directory to chroot to before running command. + :param stdin: The file object to read stdin from. + :param stdout: The file object to write stdout to. + :param stderr: The file object to write stderr to. + :param env_prune: environment variables to remove before execution + :param env_add: environment variables to add before execution + :param reset_handlers: whether to reset to SIG_DFL any signal handlers set to SIG_IGN + :param reset_lang: whether to set the locale of the child process to C + :param kwargs: Additional parameters to pass to subprocess.Popen + :return: A Popen object for the running command. + :keyword preexec_fn: A function to run before execution starts. + """ + if env_prune is None: + env_prune = [] + + # Check for and save a preexec_fn argument + preexec_fn = kwargs.pop("preexec_fn", None) + + def preexec(): + # If a target root was specificed, chroot into it + if root and root != '/': + os.chroot(root) + os.chdir("/") + + # Signal handlers set to SIG_IGN persist across exec. Reset + # these to SIG_DFL if requested. In particular this will include the + # SIGPIPE handler set by python. + if reset_handlers: + for signum in range(1, signal.NSIG): + if signal.getsignal(signum) == signal.SIG_IGN: + signal.signal(signum, signal.SIG_DFL) + + # If the user specified an additional preexec_fn argument, run it + if preexec_fn is not None: + preexec_fn() + + with program_log_lock: + program_log.info("Running... %s", " ".join(argv)) + + env = augmentEnv() + for var in env_prune: + env.pop(var, None) + + if reset_lang: + env.update({"LC_ALL": "C"}) + + if env_add: + env.update(env_add) + + # pylint: disable=subprocess-popen-preexec-fn + return subprocess.Popen(argv, + stdin=stdin, + stdout=stdout, + stderr=stderr, + close_fds=True, + preexec_fn=preexec, cwd=root, env=env, **kwargs)
+ +def _run_program(argv, root='/', stdin=None, stdout=None, env_prune=None, log_output=True, + binary_output=False, filter_stderr=False, raise_err=False, callback=None, + env_add=None, reset_handlers=True, reset_lang=True): + """ Run an external program, log the output and return it to the caller + + :param argv: The command to run and argument + :param root: The directory to chroot to before running command. + :param stdin: The file object to read stdin from. + :param stdout: Optional file object to write the output to. + :param env_prune: environment variable to remove before execution + :param log_output: whether to log the output of command + :param binary_output: whether to treat the output of command as binary data + :param filter_stderr: whether to exclude the contents of stderr from the returned output + :param raise_err: whether to raise a CalledProcessError if the returncode is non-zero + :param callback: method to call while waiting for process to finish, passed Popen object + :param env_add: environment variables to add before execution + :param reset_handlers: whether to reset to SIG_DFL any signal handlers set to SIG_IGN + :param reset_lang: whether to set the locale of the child process to C + :return: The return code of the command and the output + :raises: OSError or CalledProcessError + """ + try: + if filter_stderr: + stderr = subprocess.PIPE + else: + stderr = subprocess.STDOUT + + proc = startProgram(argv, root=root, stdin=stdin, stdout=subprocess.PIPE, stderr=stderr, + env_prune=env_prune, universal_newlines=not binary_output, + env_add=env_add, reset_handlers=reset_handlers, reset_lang=reset_lang) + + output_string = None + err_string = None + if callback: + while callback(proc) and proc.poll() is None: + try: + (output_string, err_string) = proc.communicate(timeout=1) + break + except TimeoutExpired: + pass + else: + (output_string, err_string) = proc.communicate() + if output_string: + if binary_output: + output_lines = [output_string] + else: + if output_string[-1] != "\n": + output_string = output_string + "\n" + output_lines = output_string.splitlines(True) + + if log_output: + with program_log_lock: + for line in output_lines: + program_log.info(line.strip()) + + if stdout: + stdout.write(output_string) + + # If stderr was filtered, log it separately + if filter_stderr and err_string and log_output: + err_lines = err_string.splitlines(True) + + with program_log_lock: + for line in err_lines: + program_log.info(line.strip()) + + except OSError as e: + with program_log_lock: + program_log.error("Error running %s: %s", argv[0], e.strerror) + raise + + with program_log_lock: + program_log.debug("Return code: %s", proc.returncode) + + if proc.returncode and raise_err: + output = (output_string or "") + (err_string or "") + raise subprocess.CalledProcessError(proc.returncode, argv, output) + + return (proc.returncode, output_string) + +
[docs]def execWithRedirect(command, argv, stdin=None, stdout=None, root='/', env_prune=None, + log_output=True, binary_output=False, raise_err=False, callback=None, + env_add=None, reset_handlers=True, reset_lang=True): + """ Run an external program and redirect the output to a file. + + :param command: The command to run + :param argv: The argument list + :param stdin: The file object to read stdin from. + :param stdout: Optional file object to redirect stdout and stderr to. + :param root: The directory to chroot to before running command. + :param env_prune: environment variable to remove before execution + :param log_output: whether to log the output of command + :param binary_output: whether to treat the output of command as binary data + :param raise_err: whether to raise a CalledProcessError if the returncode is non-zero + :param callback: method to call while waiting for process to finish, passed Popen object + :param env_add: environment variables to add before execution + :param reset_handlers: whether to reset to SIG_DFL any signal handlers set to SIG_IGN + :param reset_lang: whether to set the locale of the child process to C + :return: The return code of the command + """ + argv = [command] + list(argv) + return _run_program(argv, stdin=stdin, stdout=stdout, root=root, env_prune=env_prune, + log_output=log_output, binary_output=binary_output, raise_err=raise_err, callback=callback, + env_add=env_add, reset_handlers=reset_handlers, reset_lang=reset_lang)[0]
+ +
[docs]def execWithCapture(command, argv, stdin=None, root='/', log_output=True, filter_stderr=False, + raise_err=False, callback=None, env_add=None, reset_handlers=True, reset_lang=True): + """ Run an external program and capture standard out and err. + + :param command: The command to run + :param argv: The argument list + :param stdin: The file object to read stdin from. + :param root: The directory to chroot to before running command. + :param log_output: Whether to log the output of command + :param filter_stderr: Whether stderr should be excluded from the returned output + :param callback: method to call while waiting for process to finish, passed Popen object + :param env_add: environment variables to add before execution + :param reset_handlers: whether to reset to SIG_DFL any signal handlers set to SIG_IGN + :param reset_lang: whether to set the locale of the child process to C + :return: The output of the command + """ + argv = [command] + list(argv) + return _run_program(argv, stdin=stdin, root=root, log_output=log_output, filter_stderr=filter_stderr, + raise_err=raise_err, callback=callback, env_add=env_add, + reset_handlers=reset_handlers, reset_lang=reset_lang)[1]
+ +
[docs]def execReadlines(command, argv, stdin=None, root='/', env_prune=None, filter_stderr=False, + callback=lambda x: True, env_add=None, reset_handlers=True, reset_lang=True): + """ Execute an external command and return the line output of the command + in real-time. + + This method assumes that there is a reasonably low delay between the + end of output and the process exiting. If the child process closes + stdout and then keeps on truckin' there will be problems. + + NOTE/WARNING: UnicodeDecodeError will be raised if the output of the + external command can't be decoded as UTF-8. + + :param command: The command to run + :param argv: The argument list + :param stdin: The file object to read stdin from. + :param stdout: Optional file object to redirect stdout and stderr to. + :param root: The directory to chroot to before running command. + :param env_prune: environment variable to remove before execution + :param filter_stderr: Whether stderr should be excluded from the returned output + :param callback: method to call while waiting for process to finish, passed Popen object + :param env_add: environment variables to add before execution + :param reset_handlers: whether to reset to SIG_DFL any signal handlers set to SIG_IGN + :param reset_lang: whether to set the locale of the child process to C + :return: Iterator of the lines from the command + + Output from the file is not logged to program.log + This returns an iterator with the lines from the command until it has finished + """ + + class ExecLineReader(object): + """Iterator class for returning lines from a process and cleaning + up the process when the output is no longer needed. + """ + + def __init__(self, proc, argv, callback): + self._proc = proc + self._argv = argv + self._callback = callback + + def __iter__(self): + return self + + def __del__(self): + # See if the process is still running + if self._proc.poll() is None: + # Stop the process and ignore any problems that might arise + try: + self._proc.terminate() + except OSError: + pass + + def __next__(self): + # Read the next line, blocking if a line is not yet available + line = self._proc.stdout.readline().decode("utf-8") + if line == '' or not self._callback(self._proc): + # Output finished, wait for the process to end + self._proc.communicate() + + # Check for successful exit + if self._proc.returncode < 0: + raise OSError("process '%s' was killed by signal %s" % + (self._argv, -self._proc.returncode)) + elif self._proc.returncode > 0: + raise OSError("process '%s' exited with status %s" % + (self._argv, self._proc.returncode)) + raise StopIteration + + return line.strip() + + argv = [command] + argv + + if filter_stderr: + stderr = subprocess.DEVNULL + else: + stderr = subprocess.STDOUT + + try: + proc = startProgram(argv, root=root, stdin=stdin, stdout=subprocess.PIPE, stderr=stderr, bufsize=1, + env_prune=env_prune, env_add=env_add, reset_handlers=reset_handlers, reset_lang=reset_lang) + except OSError as e: + with program_log_lock: + program_log.error("Error running %s: %s", argv[0], e.strerror) + raise + + return ExecLineReader(proc, argv, callback)
+ +
[docs]def runcmd(cmd, **kwargs): + """ run execWithRedirect with raise_err=True + """ + kwargs["raise_err"] = True + return execWithRedirect(cmd[0], cmd[1:], **kwargs)
+ +
[docs]def runcmd_output(cmd, **kwargs): + """ run execWithCapture with raise_err=True + """ + kwargs["raise_err"] = True + return execWithCapture(cmd[0], cmd[1:], **kwargs)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/imgutils.html b/f29-branch/_modules/pylorax/imgutils.html new file mode 100644 index 00000000..714c4fc1 --- /dev/null +++ b/f29-branch/_modules/pylorax/imgutils.html @@ -0,0 +1,771 @@ + + + + + + + + + + + pylorax.imgutils — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.imgutils

+# imgutils.py - utility functions/classes for building disk images
+#
+# Copyright (C) 2011-2018 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s):  Will Woods <wwoods@redhat.com>
+
+import logging
+logger = logging.getLogger("pylorax.imgutils")
+
+import os, tempfile
+from os.path import join, dirname
+from subprocess import Popen, PIPE, CalledProcessError
+import sys
+import time
+import traceback
+import multiprocessing
+from time import sleep
+import shutil
+
+from pylorax.sysutils import cpfile
+from pylorax.executils import execWithRedirect, execWithCapture
+from pylorax.executils import runcmd, runcmd_output
+
+######## Functions for making container images (cpio, tar, squashfs) ##########
+
+
[docs]def compress(command, root, outfile, compression="xz", compressargs=None): + '''Make a compressed archive of the given rootdir or file. + command is a list of the archiver commands to run + compression should be "xz", "gzip", "lzma", "bzip2", or None. + compressargs will be used on the compression commandline.''' + if compression not in (None, "xz", "gzip", "lzma", "bzip2"): + raise ValueError("Unknown compression type %s" % compression) + compressargs = compressargs or ["-9"] + if compression == "xz": + compressargs.insert(0, "--check=crc32") + if compression is None: + compression = "cat" # this is a little silly + compressargs = [] + + # make compression run with multiple threads if possible + if compression in ("xz", "lzma"): + compressargs.insert(0, "-T%d" % multiprocessing.cpu_count()) + elif compression == "gzip": + compression = "pigz" + compressargs.insert(0, "-p%d" % multiprocessing.cpu_count()) + elif compression == "bzip2": + compression = "pbzip2" + compressargs.insert(0, "-p%d" % multiprocessing.cpu_count()) + + find, archive, comp = None, None, None + + try: + if os.path.isdir(root): + logger.debug("find %s -print0 |%s | %s %s > %s", root, " ".join(command), + compression, " ".join(compressargs), outfile) + + find = Popen(["find", ".", "-print0"], stdout=PIPE, cwd=root) + archive = Popen(command, stdin=find.stdout, stdout=PIPE, cwd=root) + else: + logger.debug("echo %s |%s | %s %s > %s", root, " ".join(command), + compression, " ".join(compressargs), outfile) + + archive = Popen(command, stdin=PIPE, stdout=PIPE, cwd=os.path.dirname(root)) + archive.stdin.write(os.path.basename(root).encode("utf-8") + b"\0") + archive.stdin.close() + + comp = Popen([compression] + compressargs, + stdin=archive.stdout, stdout=open(outfile, "wb")) + comp.wait() + return comp.returncode + except OSError as e: + logger.error(e) + # Kill off any hanging processes + list(p.kill() for p in (find, archive, comp) if p) + return 1
+ +
[docs]def mkcpio(root, outfile, compression="xz", compressargs=None): + compressargs = compressargs or ["-9"] + return compress(["cpio", "--null", "--quiet", "-H", "newc", "-o"], + root, outfile, compression, compressargs)
+ +
[docs]def mktar(root, outfile, compression="xz", compressargs=None, selinux=True): + compressargs = compressargs or ["-9"] + tar_cmd = ["tar", "--no-recursion"] + if selinux: + tar_cmd += ["--selinux", "--acls", "--xattrs"] + tar_cmd += ["-cf-", "--null", "-T-"] + return compress(tar_cmd, root, outfile, compression, compressargs)
+ +
[docs]def mksquashfs(rootdir, outfile, compression="default", compressargs=None): + '''Make a squashfs image containing the given rootdir.''' + compressargs = compressargs or [] + if compression != "default": + compressargs = ["-comp", compression] + compressargs + return execWithRedirect("mksquashfs", [rootdir, outfile] + compressargs)
+ +
[docs]def mkrootfsimg(rootdir, outfile, label, size=2, sysroot=""): + """ + Make rootfs image from a directory + + :param str rootdir: Root directory + :param str outfile: Path of output image file + :param str label: Filesystem label + :param int size: Size of the image in GiB, if None computed automatically + :param str sysroot: path to system (deployment) root relative to physical root + """ + if size: + fssize = size * (1024*1024*1024) # 2GB sparse file compresses down to nothin' + else: + fssize = None # Let mkext4img figure out the needed size + + mkext4img(rootdir, outfile, label=label, size=fssize)
+ + +######## Utility functions ############################################### + +
[docs]def mksparse(outfile, size): + '''use os.ftruncate to create a sparse file of the given size.''' + fobj = open(outfile, "w") + os.ftruncate(fobj.fileno(), size)
+ +
[docs]def mkqcow2(outfile, size, options=None): + '''use qemu-img to create a file of the given size. + options is a list of options passed to qemu-img + + Default format is qcow2, override by passing "-f", fmt + in options. + ''' + mkqemu_img(outfile, size, options)
+ +
[docs]def mkqemu_img(outfile, size, options=None): + '''use qemu-img to create a file of the given size. + options is a list of options passed to qemu-img + + Default format is qcow2, override by passing "-f", fmt + in options. + ''' + options = options or [] + if "-f" not in options: + options.extend(["-f", "qcow2"]) + runcmd(["qemu-img", "create"] + options + [outfile, str(size)])
+ +
[docs]def loop_waitfor(loop_dev, outfile): + """Make sure the loop device is attached to the outfile. + + It seems that on rare occasions losetup can return before the /dev/loopX is + ready for use, causing problems with mkfs. This tries to make sure that the + loop device really is associated with the backing file before continuing. + + Raise RuntimeError if it isn't setup after 5 tries. + """ + for _x in range(0,5): + runcmd(["udevadm", "settle", "--timeout", "300"]) + ## XXX Note that losetup --list output can be truncated to 64 bytes in some + ## situations. Don't use it to lookup backing file, go the other way + ## and lookup the loop for the backing file. See util-linux lib/loopdev.c + ## loopcxt_get_backing_file() + if get_loop_name(outfile) == os.path.basename(loop_dev): + return + + # If this really is a race, give it some time to settle down + time.sleep(1) + + raise RuntimeError("Unable to setup %s on %s" % (loop_dev, outfile))
+ +
[docs]def loop_attach(outfile): + """Attach a loop device to the given file. Return the loop device name. + + On rare occasions it appears that the device never shows up, some experiments + seem to indicate that it may be a race with another process using /dev/loop* devices. + + So we now try 3 times before actually failing. + + Raises CalledProcessError if losetup fails. + """ + retries = 0 + while True: + try: + retries += 1 + dev = runcmd_output(["losetup", "--find", "--show", outfile]).strip() + + # Sometimes the loop device isn't ready yet, make extra sure before returning + loop_waitfor(dev, outfile) + except RuntimeError: + # Try to setup the loop device 3 times + if retries == 3: + logger.error("loop_attach failed, retries exhausted.") + raise + logger.debug("Try %d failed, %s did not appear.", retries, dev) + break + return dev
+ +
[docs]def loop_detach(loopdev): + '''Detach the given loop device. Return False on failure.''' + return (execWithRedirect("losetup", ["--detach", loopdev]) == 0)
+ +
[docs]def get_loop_name(path): + '''Return the loop device associated with the path. + Raises RuntimeError if more than one loop is associated''' + buf = runcmd_output(["losetup", "-j", path]) + if len(buf.splitlines()) > 1: + # there should never be more than one loop device listed + raise RuntimeError("multiple loops associated with %s" % path) + name = os.path.basename(buf.split(":")[0]) + return name
+ +
[docs]def dm_attach(dev, size, name=None): + '''Attach a devicemapper device to the given device, with the given size. + If name is None, a random name will be chosen. Returns the device name. + raises CalledProcessError if dmsetup fails.''' + if name is None: + name = tempfile.mktemp(prefix="lorax.imgutils.", dir="") + runcmd(["dmsetup", "create", name, "--table", + "0 %i linear %s 0" % (size/512, dev)]) + return name
+ +
[docs]def dm_detach(dev): + '''Detach the named devicemapper device. Returns False if dmsetup fails.''' + dev = dev.replace("/dev/mapper/", "") # strip prefix, if it's there + return execWithRedirect("dmsetup", ["remove", dev])
+ +
[docs]def mount(dev, opts="", mnt=None): + '''Mount the given device at the given mountpoint, using the given opts. + opts should be a comma-separated string of mount options. + if mnt is none, a temporary directory will be created and its path will be + returned. + raises CalledProcessError if mount fails.''' + if mnt is None: + mnt = tempfile.mkdtemp(prefix="lorax.imgutils.") + logger.debug("make tmp mountdir %s", mnt) + cmd = ["mount"] + if opts: + cmd += ["-o", opts] + cmd += [dev, mnt] + runcmd(cmd) + return mnt
+ +
[docs]def umount(mnt, lazy=False, maxretry=3, retrysleep=1.0, delete=True): + '''Unmount the given mountpoint. If lazy is True, do a lazy umount (-l). + If the mount was a temporary dir created by mount, it will be deleted. + raises CalledProcessError if umount fails.''' + cmd = ["umount"] + if lazy: cmd += ["-l"] + cmd += [mnt] + count = 0 + while maxretry > 0: + try: + rv = runcmd(cmd) + except CalledProcessError: + count += 1 + if count == maxretry: + raise + logger.warning("failed to unmount %s. retrying (%d/%d)...", + mnt, count, maxretry) + if logger.getEffectiveLevel() <= logging.DEBUG: + fuser = execWithCapture("fuser", ["-vm", mnt]) + logger.debug("fuser -vm:\n%s\n", fuser) + sleep(retrysleep) + else: + break + if delete and 'lorax.imgutils' in mnt: + os.rmdir(mnt) + logger.debug("remove tmp mountdir %s", mnt) + return (rv == 0)
+ +
[docs]def copytree(src, dest, preserve=True): + '''Copy a tree of files using cp -a, thus preserving modes, timestamps, + links, acls, sparse files, xattrs, selinux contexts, etc. + If preserve is False, uses cp -R (useful for modeless filesystems) + raises CalledProcessError if copy fails.''' + logger.debug("copytree %s %s", src, dest) + cp = ["cp", "-a"] if preserve else ["cp", "-R", "-L", "--preserve=timestamps"] + cp += [join(src, "."), os.path.abspath(dest)] + runcmd(cp)
+ +
[docs]def do_grafts(grafts, dest, preserve=True): + '''Copy each of the items listed in grafts into dest. + If the key ends with '/' it's assumed to be a directory which should be + created, otherwise just the leading directories will be created.''' + for imgpath, filename in grafts.items(): + if imgpath[-1] == '/': + targetdir = join(dest, imgpath) + imgpath = imgpath[:-1] + else: + targetdir = join(dest, dirname(imgpath)) + if not os.path.isdir(targetdir): + os.makedirs(targetdir) + if os.path.isdir(filename): + copytree(filename, join(dest, imgpath), preserve) + else: + cpfile(filename, join(dest, imgpath))
+ +
[docs]def round_to_blocks(size, blocksize): + '''If size isn't a multiple of blocksize, round up to the next multiple''' + diff = size % blocksize + if diff or not size: + size += blocksize - diff + return size
+ +# TODO: move filesystem data outside this function +
[docs]def estimate_size(rootdir, graft=None, fstype=None, blocksize=4096, overhead=256): + graft = graft or {} + getsize = lambda f: os.lstat(f).st_size + if fstype == "btrfs": + overhead = 64*1024 # don't worry, it's all sparse + if fstype == "hfsplus": + overhead = 200 # hack to deal with two bootloader copies + if fstype in ("vfat", "msdos"): + blocksize = 2048 + getsize = lambda f: os.stat(f).st_size # no symlinks, count as copies + total = overhead*blocksize + dirlist = list(graft.values()) + if rootdir: + dirlist.append(rootdir) + for root in dirlist: + for top, dirs, files in os.walk(root): + for f in files + dirs: + total += round_to_blocks(getsize(join(top,f)), blocksize) + if fstype == "btrfs": + total = max(256*1024*1024, total) # btrfs minimum size: 256MB + logger.info("Size of %s block %s fs at %s estimated to be %s", blocksize, fstype, rootdir, total) + return total
+ +######## Execution contexts - use with the 'with' statement ############## + +
[docs]class LoopDev(object): + def __init__(self, filename, size=None): + self.loopdev = None + self.filename = filename + if size: + mksparse(self.filename, size) + def __enter__(self): + self.loopdev = loop_attach(self.filename) + return self.loopdev + def __exit__(self, exc_type, exc_value, tracebk): + loop_detach(self.loopdev)
+ +
[docs]class DMDev(object): + def __init__(self, dev, size, name=None): + self.mapperdev = None + (self.dev, self.size, self.name) = (dev, size, name) + def __enter__(self): + self.mapperdev = dm_attach(self.dev, self.size, self.name) + return self.mapperdev + def __exit__(self, exc_type, exc_value, tracebk): + dm_detach(self.mapperdev)
+ +
[docs]class Mount(object): + def __init__(self, dev, opts="", mnt=None): + (self.dev, self.opts, self.mnt) = (dev, opts, mnt) + def __enter__(self): + self.mnt = mount(self.dev, self.opts, self.mnt) + return self.mnt + def __exit__(self, exc_type, exc_value, tracebk): + umount(self.mnt)
+ +
[docs]def kpartx_disk_img(disk_img): + """Attach a disk image's partitions to /dev/loopX using kpartx + + :param disk_img: The full path to a partitioned disk image + :type disk_img: str + :returns: list of (loopXpN, size) + :rtype: list of tuples + """ + # Example kpartx output + # kpartx -p p -v -a /tmp/diskV2DiCW.im + # add map loop2p1 (253:2): 0 3481600 linear /dev/loop2 2048 + # add map loop2p2 (253:3): 0 614400 linear /dev/loop2 3483648 + kpartx_output = runcmd_output(["kpartx", "-v", "-a", "-s", disk_img]) + logger.debug(kpartx_output) + + # list of (deviceName, sizeInBytes) + loop_devices = [] + for line in kpartx_output.splitlines(): + # add map loop2p3 (253:4): 0 7139328 linear /dev/loop2 528384 + # 3rd element is size in 512 byte blocks + if line.startswith("add map "): + fields = line[8:].split() + loop_devices.append( (fields[0], int(fields[3])*512) ) + return loop_devices
+ +
[docs]class PartitionMount(object): + """ Mount a partitioned image file using kpartx """ + def __init__(self, disk_img, mount_ok=None, submount=None): + """ + :param str disk_img: The full path to a partitioned disk image + :param mount_ok: A function that is passed the mount point and + returns True if it should be mounted. + :param str submount: Directory inside mount_dir to mount at + + If mount_ok is not set it will look for /etc/passwd + + If the partition is found it will be mounted under a temporary + directory and self.temp_dir set to it. If submount is passed it will be + created and mounted there instead, with self.mount_dir set to point to + it. self.mount_dev is set to the loop device, and self.mount_size is + set to the size of the partition. + + When no subdir is passed self.temp_dir and self.mount_dir will be the same. + """ + self.mount_dev = None + self.mount_size = None + self.mount_dir = None + self.disk_img = disk_img + self.mount_ok = mount_ok + self.submount = submount + self.temp_dir = None + + # Default is to mount partition with /etc/passwd + if not self.mount_ok: + self.mount_ok = lambda mount_dir: os.path.isfile(mount_dir+"/etc/passwd") + + # list of (deviceName, sizeInBytes) + self.loop_devices = kpartx_disk_img(self.disk_img) + + def __enter__(self): + # Mount the device selected by mount_ok, if possible + self.temp_dir = tempfile.mkdtemp() + if self.submount: + mount_dir = os.path.normpath(os.path.sep.join([self.temp_dir, self.submount])) + os.makedirs(mount_dir, mode=0o755, exist_ok=True) + else: + mount_dir = self.temp_dir + for dev, size in self.loop_devices: + try: + mount( "/dev/mapper/"+dev, mnt=mount_dir ) + if self.mount_ok(mount_dir): + self.mount_dir = mount_dir + self.mount_dev = dev + self.mount_size = size + break + umount( mount_dir ) + except CalledProcessError: + logger.debug(traceback.format_exc()) + if self.mount_dir: + logger.info("Partition mounted on %s size=%s", self.mount_dir, self.mount_size) + else: + logger.debug("Unable to mount anything from %s", self.disk_img) + os.rmdir(self.temp_dir) + self.temp_dir = None + return self + + def __exit__(self, exc_type, exc_value, tracebk): + if self.temp_dir: + umount(self.mount_dir) + shutil.rmtree(self.temp_dir) + self.mount_dir = None + self.temp_dir = None + execWithRedirect("kpartx", ["-d", "-s", self.disk_img])
+ + +######## Functions for making filesystem images ########################## + +
[docs]def mkfsimage(fstype, rootdir, outfile, size=None, mkfsargs=None, mountargs="", graft=None): + '''Generic filesystem image creation function. + fstype should be a filesystem type - "mkfs.${fstype}" must exist. + graft should be a dict: {"some/path/in/image": "local/file/or/dir"}; + if the path ends with a '/' it's assumed to be a directory. + Will raise CalledProcessError if something goes wrong.''' + mkfsargs = mkfsargs or [] + graft = graft or {} + preserve = (fstype not in ("msdos", "vfat")) + if not size: + size = estimate_size(rootdir, graft, fstype) + with LoopDev(outfile, size) as loopdev: + try: + runcmd(["mkfs.%s" % fstype] + mkfsargs + [loopdev]) + except CalledProcessError as e: + logger.error("mkfs exited with a non-zero return code: %d", e.returncode) + logger.error(e.output) + sys.exit(e.returncode) + + with Mount(loopdev, mountargs) as mnt: + if rootdir: + copytree(rootdir, mnt, preserve) + do_grafts(graft, mnt, preserve) + + # Save information about filesystem usage + execWithRedirect("df", [mnt]) + + # Make absolutely sure that the data has been written + runcmd(["sync"])
+ +# convenience functions with useful defaults +
[docs]def mkdosimg(rootdir, outfile, size=None, label="", mountargs="shortname=winnt,umask=0077", graft=None): + graft = graft or {} + mkfsargs = ["-n", label] + if 'SOURCE_DATE_EPOCH' in os.environ: + mkfsargs.extend(["-i", + "{:x}".format(int(os.environ['SOURCE_DATE_EPOCH']))]) + mkfsimage("msdos", rootdir, outfile, size, mountargs=mountargs, + mkfsargs=mkfsargs, graft=graft)
+ +
[docs]def mkext4img(rootdir, outfile, size=None, label="", mountargs="", graft=None): + graft = graft or {} + mkfsimage("ext4", rootdir, outfile, size, mountargs=mountargs, + mkfsargs=["-L", label, "-b", "4096", "-m", "0"], graft=graft)
+ +
[docs]def mkbtrfsimg(rootdir, outfile, size=None, label="", mountargs="", graft=None): + graft = graft or {} + mkfsimage("btrfs", rootdir, outfile, size, mountargs=mountargs, + mkfsargs=["-L", label], graft=graft)
+ +
[docs]def mkhfsimg(rootdir, outfile, size=None, label="", mountargs="", graft=None): + graft = graft or {} + mkfsimage("hfsplus", rootdir, outfile, size, mountargs=mountargs, + mkfsargs=["-v", label], graft=graft)
+ +
[docs]def mkfsimage_from_disk(diskimage, fsimage, img_size=None, label="Anaconda"): + """ + Copy the / partition of a partitioned disk image to an un-partitioned + disk image. + + :param str diskimage: The full path to partitioned disk image with a / + :param str fsimage: The full path of the output fs image file + :param int img_size: Optional size of the fsimage in MiB or None to make + it as small as possible + :param str label: The label to apply to the image. Defaults to "Anaconda" + """ + with PartitionMount(diskimage) as img_mount: + if not img_mount or not img_mount.mount_dir: + return None + + logger.info("Creating fsimage %s (%s)", fsimage, img_size or "minimized") + if img_size: + # convert to Bytes + img_size *= 1024**2 + + mkext4img(img_mount.mount_dir, fsimage, size=img_size, label=label)
+ +
[docs]def default_image_name(compression, basename): + """ Return a default image name with the correct suffix for the compression type. + + :param str compression: Compression type + :param str basename: Base filename + :returns: basename with compression suffix + + If the compression is unknown it defaults to xz + """ + SUFFIXES = {"xz": ".xz", "gzip": ".gz", "bzip2": ".bz2", "lzma": ".lzma"} + return basename + SUFFIXES.get(compression, ".xz")
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/installer.html b/f29-branch/_modules/pylorax/installer.html new file mode 100644 index 00000000..616026d6 --- /dev/null +++ b/f29-branch/_modules/pylorax/installer.html @@ -0,0 +1,883 @@ + + + + + + + + + + + pylorax.installer — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.installer

+#
+# Copyright (C) 2011-2018  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, see <http://www.gnu.org/licenses/>.
+#
+import logging
+log = logging.getLogger("pylorax")
+
+import glob
+import json
+from math import ceil
+import os
+import subprocess
+import shutil
+import socket
+import tempfile
+
+# Use the Lorax treebuilder branch for iso creation
+from pylorax.executils import execWithRedirect, execReadlines
+from pylorax.imgutils import PartitionMount, mksparse, mkext4img, loop_detach
+from pylorax.imgutils import get_loop_name, dm_detach, mount, umount
+from pylorax.imgutils import mkqemu_img, mktar, mkcpio, mkfsimage_from_disk
+from pylorax.monitor import LogMonitor
+from pylorax.mount import IsoMountpoint
+from pylorax.sysutils import joinpaths
+from pylorax.treebuilder import udev_escape
+
+
+ROOT_PATH = "/mnt/sysimage/"
+
+
[docs]class InstallError(Exception): + pass
+ + +
[docs]def create_vagrant_metadata(path, size=0): + """ Create a default Vagrant metadata.json file + + :param str path: Path to metadata.json file + :param int size: Disk size in MiB + """ + metadata = { "provider":"libvirt", "format":"qcow2", "virtual_size": ceil(size / 1024) } + with open(path, "wt") as f: + json.dump(metadata, f, indent=4)
+ + +
[docs]def update_vagrant_metadata(path, size): + """ Update the Vagrant metadata.json file + + :param str path: Path to metadata.json file + :param int size: Disk size in MiB + + This function makes sure that the provider, format and virtual size of the + metadata file are set correctly. All other values are left untouched. + """ + with open(path, "rt") as f: + try: + metadata = json.load(f) + except ValueError as e: + log.error("Problem reading metadata file %s: %s", path, e) + return + + metadata["provider"] = "libvirt" + metadata["format"] = "qcow2" + metadata["virtual_size"] = ceil(size / 1024) + with open(path, "wt") as f: + json.dump(metadata, f, indent=4)
+ + +
[docs]def find_free_port(start=5900, end=5999, host="127.0.0.1"): + """ Return first free port in range. + + :param int start: Starting port number + :param int end: Ending port number + :param str host: Host IP to search + :returns: First free port or -1 if none found + :rtype: int + """ + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + for port in range(start, end+1): + try: + s.bind((host, port)) + s.close() + return port + except OSError: + pass + + return -1
+ +
[docs]def append_initrd(initrd, files): + """ Append files to an initrd. + + :param str initrd: Path to initrd + :param list files: list of file paths to add + :returns: Path to a new initrd + :rtype: str + + The files are added to the initrd by creating a cpio image + of the files (stored at /) and writing the cpio to the end of a + copy of the initrd. + + The initrd is not changed, a copy is made before appending the + cpio archive. + """ + qemu_initrd = tempfile.mktemp(prefix="lmc-initrd-", suffix=".img") + shutil.copy2(initrd, qemu_initrd) + ks_dir = tempfile.mkdtemp(prefix="lmc-ksdir-") + for ks in files: + shutil.copy2(ks, ks_dir) + ks_initrd = tempfile.mktemp(prefix="lmc-ks-", suffix=".img") + mkcpio(ks_dir, ks_initrd) + shutil.rmtree(ks_dir) + with open(qemu_initrd, "ab") as initrd_fp: + with open(ks_initrd, "rb") as ks_fp: + while True: + data = ks_fp.read(1024**2) + if not data: + break + initrd_fp.write(data) + os.unlink(ks_initrd) + + return qemu_initrd
+ +
[docs]class QEMUInstall(object): + """ + Run qemu using an iso and a kickstart + """ + # Mapping of arch to qemu command + QEMU_CMDS = {"x86_64": "qemu-system-x86_64", + "i386": "qemu-system-i386", + "arm": "qemu-system-arm", + "aarch64": "qemu-system-aarch64", + "ppc": "qemu-system-ppc", + "ppc64": "qemu-system-ppc64" + } + + def __init__(self, opts, iso, ks_paths, disk_img, img_size=2048, + kernel_args=None, memory=1024, vcpus=None, vnc=None, arch=None, + cancel_func=None, virtio_host="127.0.0.1", virtio_port=6080, + image_type=None, boot_uefi=False, ovmf_path=None): + """ + Start the installation + + :param iso: Information about the iso to use for the installation + :type iso: IsoMountpoint + :param list ks_paths: Paths to kickstart files. All are injected, the + first one is the one executed. + :param str disk_img: Path to a disk image, created it it doesn't exist + :param int img_size: The image size, in MiB, to create if it doesn't exist + :param str kernel_args: Extra kernel arguments to pass on the kernel cmdline + :param int memory: Amount of RAM to assign to the virt, in MiB + :param int vcpus: Number of virtual cpus + :param str vnc: Arguments to pass to qemu -display + :param str arch: Optional architecture to use in the virt + :param cancel_func: Function that returns True if the installation fails + :type cancel_func: function + :param str virtio_host: Hostname to connect virtio log to + :param int virtio_port: Port to connect virtio log to + :param str image_type: Type of qemu-img disk to create, or None. + :param bool boot_uefi: Use OVMF to boot the VM in UEFI mode + :param str ovmf_path: Path to the OVMF firmware + """ + # Lookup qemu-system- for arch if passed, or try to guess using host arch + qemu_cmd = [self.QEMU_CMDS.get(arch or os.uname().machine, "qemu-system-"+os.uname().machine)] + if not os.path.exists("/usr/bin/"+qemu_cmd[0]): + raise InstallError("%s does not exist, cannot run qemu" % qemu_cmd[0]) + + qemu_cmd += ["-no-user-config"] + qemu_cmd += ["-m", str(memory)] + if vcpus: + qemu_cmd += ["-smp", str(vcpus)] + + if not opts.no_kvm and os.path.exists("/dev/kvm"): + qemu_cmd += ["-machine", "accel=kvm"] + + if boot_uefi: + qemu_cmd += ["-machine", "q35,smm=on"] + qemu_cmd += ["-global", "driver=cfi.pflash01,property=secure,value=on"] + + # Copy the initrd from the iso, create a cpio archive of the kickstart files + # and append it to the temporary initrd. + qemu_initrd = append_initrd(iso.initrd, ks_paths) + qemu_cmd += ["-kernel", iso.kernel] + qemu_cmd += ["-initrd", qemu_initrd] + + # Add the disk and cdrom + if not os.path.isfile(disk_img): + mksparse(disk_img, img_size * 1024**2) + drive_args = "file=%s" % disk_img + drive_args += ",cache=unsafe,discard=unmap" + if image_type: + drive_args += ",format=%s" % image_type + else: + drive_args += ",format=raw" + qemu_cmd += ["-drive", drive_args] + + drive_args = "file=%s,media=cdrom,readonly=on" % iso.iso_path + qemu_cmd += ["-drive", drive_args] + + # Setup the cmdline args + # ====================== + cmdline_args = "ks=file:/%s" % os.path.basename(ks_paths[0]) + cmdline_args += " inst.stage2=hd:LABEL=%s" % udev_escape(iso.label) + if opts.proxy: + cmdline_args += " inst.proxy=%s" % opts.proxy + if kernel_args: + cmdline_args += " "+kernel_args + cmdline_args += " inst.text inst.cmdline" + + qemu_cmd += ["-append", cmdline_args] + + if not opts.vnc: + vnc_port = find_free_port() + if vnc_port == -1: + raise InstallError("No free VNC ports") + display_args = "vnc=127.0.0.1:%d" % (vnc_port - 5900) + else: + display_args = opts.vnc + log.info("qemu %s", display_args) + qemu_cmd += ["-nographic", "-monitor", "none", "-serial", "null", "-display", display_args ] + + # Setup the virtio log port + qemu_cmd += ["-device", "virtio-serial-pci,id=virtio-serial0"] + qemu_cmd += ["-device", "virtserialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0" + ",id=channel0,name=org.fedoraproject.anaconda.log.0"] + qemu_cmd += ["-chardev", "socket,id=charchannel0,host=%s,port=%s" % (virtio_host, virtio_port)] + + # Pass through rng from host + if opts.with_rng != "none": + qemu_cmd += ["-object", "rng-random,id=virtio-rng0,filename=%s" % opts.with_rng] + if boot_uefi: + qemu_cmd += ["-device", "virtio-rng-pci,rng=virtio-rng0,id=rng0,bus=pcie.0,addr=0x9"] + else: + qemu_cmd += ["-device", "virtio-rng-pci,rng=virtio-rng0,id=rng0,bus=pci.0,addr=0x9"] + + if boot_uefi and ovmf_path: + qemu_cmd += ["-drive", "file=%s/OVMF_CODE.secboot.fd,if=pflash,format=raw,unit=0,readonly=on" % ovmf_path] + + # Make a copy of the OVMF_VARS.secboot.fd for this run + ovmf_vars = tempfile.mktemp(prefix="lmc-OVMF_VARS-", suffix=".fd") + shutil.copy2(joinpaths(ovmf_path, "/OVMF_VARS.secboot.fd"), ovmf_vars) + + qemu_cmd += ["-drive", "file=%s,if=pflash,format=raw,unit=1" % ovmf_vars] + + log.info("Running qemu") + log.debug(qemu_cmd) + try: + execWithRedirect(qemu_cmd[0], qemu_cmd[1:], reset_lang=False, raise_err=True, + callback=lambda p: not (cancel_func and cancel_func())) + except subprocess.CalledProcessError as e: + log.error("Running qemu failed:") + log.error("cmd: %s", " ".join(e.cmd)) + log.error("output: %s", e.output or "") + raise InstallError("QEMUInstall failed") + except (OSError, KeyboardInterrupt) as e: + log.error("Running qemu failed: %s", str(e)) + raise InstallError("QEMUInstall failed") + finally: + os.unlink(qemu_initrd) + if boot_uefi and ovmf_path: + os.unlink(ovmf_vars) + + if cancel_func and cancel_func(): + log.error("Installation error detected. See logfile for details.") + raise InstallError("QEMUInstall failed") + else: + log.info("Installation finished without errors.")
+ + +
[docs]def novirt_cancel_check(cancel_funcs, proc): + """ + Check to see if there has been an error in the logs + + :param cancel_funcs: list of functions to call, True from any one cancels the build + :type cancel_funcs: list + :param proc: Popen object for the anaconda process + :type proc: subprocess.Popen + :returns: True if the process has been terminated + + The cancel_funcs functions should return a True if an error has been detected. + When an error is detected the process is terminated and this returns True + """ + for f in cancel_funcs: + if f(): + proc.terminate() + return True + return False
+ + +
[docs]def anaconda_cleanup(dirinstall_path): + """ + Cleanup any leftover mounts from anaconda + + :param str dirinstall_path: Path where anaconda mounts things + :returns: True if cleanups were successful. False if any of them failed. + + If anaconda crashes it may leave things mounted under this path. It will + typically be set to /mnt/sysimage/ + + Attempts to cleanup may also fail. Catch these and continue trying the + other mountpoints. + """ + rc = True + dirinstall_path = os.path.abspath(dirinstall_path) + # unmount filesystems + for mounted in reversed(open("/proc/mounts").readlines()): + (_device, mountpoint, _rest) = mounted.split(" ", 2) + if mountpoint.startswith(dirinstall_path) and os.path.ismount(mountpoint): + try: + umount(mountpoint) + except subprocess.CalledProcessError: + log.error("Cleanup of %s failed. See program.log for details", mountpoint) + rc = False + return rc
+ + +
[docs]def novirt_install(opts, disk_img, disk_size, cancel_func=None, tar_img=None): + """ + Use Anaconda to install to a disk image + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str disk_img: The full path to the disk image to be created + :param int disk_size: The size of the disk_img in MiB + :param cancel_func: Function that returns True to cancel build + :type cancel_func: function + :param str tar_img: For make_tar_disk, the path to final tarball to be created + + This method runs anaconda to create the image and then based on the opts + passed creates a qemu disk image or tarfile. + """ + dirinstall_path = ROOT_PATH + + # Clean up /tmp/ from previous runs to prevent stale info from being used + for path in ["/tmp/yum.repos.d/", "/tmp/yum.cache/"]: + if os.path.isdir(path): + shutil.rmtree(path) + + args = ["--kickstart", opts.ks[0], "--cmdline", "--loglevel", "debug"] + if opts.anaconda_args: + for arg in opts.anaconda_args: + args += arg.split(" ", 1) + if opts.proxy: + args += ["--proxy", opts.proxy] + if opts.armplatform: + args += ["--armplatform", opts.armplatform] + + if opts.make_iso or opts.make_fsimage or opts.make_pxe_live: + # Make a blank fs image + args += ["--dirinstall"] + + mkext4img(None, disk_img, label=opts.fs_label, size=disk_size * 1024**2) + if not os.path.isdir(dirinstall_path): + os.mkdir(dirinstall_path) + mount(disk_img, opts="loop", mnt=dirinstall_path) + elif opts.make_tar or opts.make_oci: + # Install under dirinstall_path, make sure it starts clean + if os.path.exists(dirinstall_path): + shutil.rmtree(dirinstall_path) + + if opts.make_oci: + # OCI installs under /rootfs/ + dirinstall_path = joinpaths(dirinstall_path, "rootfs") + args += ["--dirinstall", dirinstall_path] + else: + args += ["--dirinstall"] + + os.makedirs(dirinstall_path) + else: + args += ["--image", disk_img] + + # Create the sparse image + mksparse(disk_img, disk_size * 1024**2) + + log_monitor = LogMonitor(timeout=opts.timeout) + args += ["--remotelog", "%s:%s" % (log_monitor.host, log_monitor.port)] + cancel_funcs = [log_monitor.server.log_check] + if cancel_func is not None: + cancel_funcs.append(cancel_func) + + # Make sure anaconda has the right product and release + log.info("Running anaconda.") + try: + for line in execReadlines("anaconda", args, reset_lang=False, + env_add={"ANACONDA_PRODUCTNAME": opts.project, + "ANACONDA_PRODUCTVERSION": opts.releasever}, + callback=lambda p: not novirt_cancel_check(cancel_funcs, p)): + log.info(line) + + # Make sure the new filesystem is correctly labeled + setfiles_args = ["-e", "/proc", "-e", "/sys", + "/etc/selinux/targeted/contexts/files/file_contexts", "/"] + + if "--dirinstall" in args: + # setfiles may not be available, warn instead of fail + try: + execWithRedirect("setfiles", setfiles_args, root=dirinstall_path) + except (subprocess.CalledProcessError, OSError) as e: + log.warning("Running setfiles on install tree failed: %s", str(e)) + else: + with PartitionMount(disk_img) as img_mount: + if img_mount and img_mount.mount_dir: + try: + execWithRedirect("setfiles", setfiles_args, root=img_mount.mount_dir) + except (subprocess.CalledProcessError, OSError) as e: + log.warning("Running setfiles on install tree failed: %s", str(e)) + + # For image installs, run fstrim to discard unused blocks. This way + # unused blocks do not need to be allocated for sparse image types + execWithRedirect("fstrim", [img_mount.mount_dir]) + + except (subprocess.CalledProcessError, OSError) as e: + log.error("Running anaconda failed: %s", e) + raise InstallError("novirt_install failed") + finally: + log_monitor.shutdown() + + # Move the anaconda logs over to a log directory + log_dir = os.path.abspath(os.path.dirname(opts.logfile)) + log_anaconda = joinpaths(log_dir, "anaconda") + if not os.path.isdir(log_anaconda): + os.mkdir(log_anaconda) + for l in glob.glob("/tmp/*log")+glob.glob("/tmp/anaconda-tb-*"): + shutil.copy2(l, log_anaconda) + os.unlink(l) + + # Make sure any leftover anaconda mounts have been cleaned up + if not anaconda_cleanup(dirinstall_path): + raise InstallError("novirt_install cleanup of anaconda mounts failed.") + + if not opts.make_iso and not opts.make_fsimage and not opts.make_pxe_live: + dm_name = os.path.splitext(os.path.basename(disk_img))[0] + + # Remove device-mapper for partitions and disk + log.debug("Removing device-mapper setup on %s", dm_name) + for d in sorted(glob.glob("/dev/mapper/"+dm_name+"*"), reverse=True): + dm_detach(d) + + log.debug("Removing loop device for %s", disk_img) + loop_detach("/dev/"+get_loop_name(disk_img)) + + # qemu disk image is used by bare qcow2 images and by Vagrant + if opts.image_type: + log.info("Converting %s to %s", disk_img, opts.image_type) + qemu_args = [] + for arg in opts.qemu_args: + qemu_args += arg.split(" ", 1) + + # convert the image to the selected format + if "-O" not in qemu_args: + qemu_args.extend(["-O", opts.image_type]) + qemu_img = tempfile.mktemp(prefix="lmc-disk-", suffix=".img") + execWithRedirect("qemu-img", ["convert"] + qemu_args + [disk_img, qemu_img], raise_err=True) + if not opts.make_vagrant: + execWithRedirect("mv", ["-f", qemu_img, disk_img], raise_err=True) + else: + # Take the new qcow2 image and package it up for Vagrant + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + vagrant_dir = tempfile.mkdtemp(prefix="lmc-tmpdir-") + metadata_path = joinpaths(vagrant_dir, "metadata.json") + execWithRedirect("mv", ["-f", qemu_img, joinpaths(vagrant_dir, "box.img")], raise_err=True) + if opts.vagrant_metadata: + shutil.copy2(opts.vagrant_metadata, metadata_path) + else: + create_vagrant_metadata(metadata_path) + update_vagrant_metadata(metadata_path, disk_size) + if opts.vagrantfile: + shutil.copy2(opts.vagrantfile, joinpaths(vagrant_dir, "vagrantfile")) + + log.info("Creating Vagrant image") + rc = mktar(vagrant_dir, disk_img, opts.compression, compress_args, selinux=False) + if rc: + raise InstallError("novirt_install mktar failed: rc=%s" % rc) + shutil.rmtree(vagrant_dir) + elif opts.make_tar: + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + rc = mktar(dirinstall_path, disk_img, opts.compression, compress_args) + shutil.rmtree(dirinstall_path) + + if rc: + raise InstallError("novirt_install mktar failed: rc=%s" % rc) + elif opts.make_oci: + # An OCI image places the filesystem under /rootfs/ and adds the json files at the top + # And then creates a tar of the whole thing. + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + shutil.copy2(opts.oci_config, ROOT_PATH) + shutil.copy2(opts.oci_runtime, ROOT_PATH) + rc = mktar(ROOT_PATH, disk_img, opts.compression, compress_args) + + if rc: + raise InstallError("novirt_install mktar failed: rc=%s" % rc) + else: + # For raw disk images, use fallocate to deallocate unused space + execWithRedirect("fallocate", ["--dig-holes", disk_img], raise_err=True) + + # For make_tar_disk, wrap the result in a tar file, and remove the original disk image. + if opts.make_tar_disk: + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + rc = mktar(disk_img, tar_img, opts.compression, compress_args, selinux=False) + + if rc: + raise InstallError("novirt_install mktar failed: rc=%s" % rc) + + os.unlink(disk_img)
+ +
[docs]def virt_install(opts, install_log, disk_img, disk_size, cancel_func=None, tar_img=None): + """ + Use qemu to install to a disk image + + :param opts: options passed to livemedia-creator + :type opts: argparse options + :param str install_log: The path to write the log from qemu + :param str disk_img: The full path to the disk image to be created + :param int disk_size: The size of the disk_img in MiB + :param cancel_func: Function that returns True to cancel build + :type cancel_func: function + :param str tar_img: For make_tar_disk, the path to final tarball to be created + + This uses qemu with a boot.iso and a kickstart to create a disk + image and then optionally, based on the opts passed, creates tarfile. + """ + iso_mount = IsoMountpoint(opts.iso, opts.location) + if not iso_mount.stage2: + iso_mount.umount() + raise InstallError("ISO is missing stage2, cannot continue") + + log_monitor = LogMonitor(install_log, timeout=opts.timeout) + cancel_funcs = [log_monitor.server.log_check] + if cancel_func is not None: + cancel_funcs.append(cancel_func) + + kernel_args = "" + if opts.kernel_args: + kernel_args += opts.kernel_args + if opts.proxy: + kernel_args += " proxy="+opts.proxy + + if opts.image_type and not opts.make_fsimage: + qemu_args = [] + for arg in opts.qemu_args: + qemu_args += arg.split(" ", 1) + if "-f" not in qemu_args: + qemu_args += ["-f", opts.image_type] + + mkqemu_img(disk_img, disk_size*1024**2, qemu_args) + + if opts.make_fsimage or opts.make_tar or opts.make_oci: + diskimg_path = tempfile.mktemp(prefix="lmc-disk-", suffix=".img") + else: + diskimg_path = disk_img + + try: + QEMUInstall(opts, iso_mount, opts.ks, diskimg_path, disk_size, + kernel_args, opts.ram, opts.vcpus, opts.vnc, opts.arch, + cancel_func = lambda : any(f() for f in cancel_funcs), + virtio_host = log_monitor.host, + virtio_port = log_monitor.port, + image_type=opts.image_type, boot_uefi=opts.virt_uefi, + ovmf_path=opts.ovmf_path) + log_monitor.shutdown() + except InstallError as e: + log.error("VirtualInstall failed: %s", e) + raise + finally: + log.info("unmounting the iso") + iso_mount.umount() + + if log_monitor.server.log_check(): + if not log_monitor.server.error_line and opts.timeout: + msg = "virt_install failed due to timeout" + else: + msg = "virt_install failed on line: %s" % log_monitor.server.error_line + raise InstallError(msg) + elif cancel_func and cancel_func(): + raise InstallError("virt_install canceled by cancel_func") + + if opts.make_fsimage: + mkfsimage_from_disk(diskimg_path, disk_img, disk_size, label=opts.fs_label) + os.unlink(diskimg_path) + elif opts.make_tar: + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + with PartitionMount(diskimg_path) as img_mount: + if img_mount and img_mount.mount_dir: + rc = mktar(img_mount.mount_dir, disk_img, opts.compression, compress_args) + else: + rc = 1 + os.unlink(diskimg_path) + + if rc: + raise InstallError("virt_install failed") + elif opts.make_oci: + # An OCI image places the filesystem under /rootfs/ and adds the json files at the top + # And then creates a tar of the whole thing. + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + with PartitionMount(diskimg_path, submount="rootfs") as img_mount: + if img_mount and img_mount.temp_dir: + shutil.copy2(opts.oci_config, img_mount.temp_dir) + shutil.copy2(opts.oci_runtime, img_mount.temp_dir) + rc = mktar(img_mount.temp_dir, disk_img, opts.compression, compress_args) + else: + rc = 1 + os.unlink(diskimg_path) + + if rc: + raise InstallError("virt_install failed") + elif opts.make_vagrant: + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + vagrant_dir = tempfile.mkdtemp(prefix="lmc-tmpdir-") + metadata_path = joinpaths(vagrant_dir, "metadata.json") + execWithRedirect("mv", ["-f", disk_img, joinpaths(vagrant_dir, "box.img")], raise_err=True) + if opts.vagrant_metadata: + shutil.copy2(opts.vagrant_metadata, metadata_path) + else: + create_vagrant_metadata(metadata_path) + update_vagrant_metadata(metadata_path, disk_size) + if opts.vagrantfile: + shutil.copy2(opts.vagrantfile, joinpaths(vagrant_dir, "vagrantfile")) + + rc = mktar(vagrant_dir, disk_img, opts.compression, compress_args, selinux=False) + if rc: + raise InstallError("virt_install failed") + shutil.rmtree(vagrant_dir) + + # For make_tar_disk, wrap the result in a tar file, and remove the original disk image. + if opts.make_tar_disk: + compress_args = [] + for arg in opts.compress_args: + compress_args += arg.split(" ", 1) + + rc = mktar(disk_img, tar_img, opts.compression, compress_args, selinux=False) + + if rc: + raise InstallError("virt_install mktar failed: rc=%s" % rc) + + os.unlink(disk_img)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/ltmpl.html b/f29-branch/_modules/pylorax/ltmpl.html new file mode 100644 index 00000000..1cc1c24f --- /dev/null +++ b/f29-branch/_modules/pylorax/ltmpl.html @@ -0,0 +1,1104 @@ + + + + + + + + + + + pylorax.ltmpl — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.ltmpl

+#
+# ltmpl.py
+#
+# Copyright (C) 2009-2018  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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#                     Will Woods <wwoods@redhat.com>
+#
+
+import logging
+logger = logging.getLogger("pylorax.ltmpl")
+
+import os, re, glob, shlex, fnmatch
+from os.path import basename, isdir
+from subprocess import CalledProcessError
+import shutil
+
+from pylorax.sysutils import joinpaths, cpfile, mvfile, replace, remove
+from pylorax.dnfhelper import LoraxDownloadCallback, LoraxRpmCallback
+from pylorax.base import DataHolder
+from pylorax.executils import runcmd, runcmd_output
+from pylorax.imgutils import mkcpio
+
+from mako.lookup import TemplateLookup
+from mako.exceptions import text_error_template
+import sys, traceback
+import struct
+import dnf
+import collections
+
+
[docs]class LoraxTemplate(object): + def __init__(self, directories=None): + directories = directories or ["/usr/share/lorax"] + # we have to add ["/"] to the template lookup directories or the + # file includes won't work properly for absolute paths + self.directories = ["/"] + directories + +
[docs] def parse(self, template_file, variables): + lookup = TemplateLookup(directories=self.directories) + template = lookup.get_template(template_file) + + try: + textbuf = template.render(**variables) + except: + logger.error("Problem rendering %s (%s):", template_file, variables) + logger.error(text_error_template().render()) + raise + + # split, strip and remove empty lines + lines = textbuf.splitlines() + lines = [line.strip() for line in lines] + lines = [line for line in lines if line] + + # remove comments + lines = [line for line in lines if not line.startswith("#")] + + # split with shlex and perform brace expansion. This can fail, so we unroll the loop + # for better error reporting. + expanded_lines = [] + try: + for line in lines: + expanded_lines.append(split_and_expand(line)) + except Exception as e: + logger.error('shlex error processing "%s": %s', line, str(e)) + raise + return expanded_lines
+ +
[docs]def split_and_expand(line): + return [exp for word in shlex.split(line) for exp in brace_expand(word)]
+ +
[docs]def brace_expand(s): + if not ('{' in s and ',' in s and '}' in s): + yield s + else: + right = s.find('}') + left = s[:right].rfind('{') + (prefix, choices, suffix) = (s[:left], s[left+1:right], s[right+1:]) + for choice in choices.split(','): + for alt in brace_expand(prefix+choice+suffix): + yield alt
+ +
[docs]def rglob(pathname, root="/", fatal=False): + seen = set() + rootlen = len(root)+1 + for f in glob.iglob(joinpaths(root, pathname)): + if f not in seen: + seen.add(f) + yield f[rootlen:] # remove the root to produce relative path + if fatal and not seen: + raise IOError("nothing matching %s in %s" % (pathname, root))
+ +
[docs]def rexists(pathname, root=""): + # Generator is always True, even with no values; + # bool(rglob(...)) won't work here. + for _path in rglob(pathname, root): + return True + return False
+ +
[docs]class TemplateRunner(object): + ''' + This class parses and executes Lorax templates. Sample usage: + + # install a bunch of packages + runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, dbo=dnf_obj) + runner.run("install-packages.ltmpl") + NOTES: + + * Parsing procedure is roughly: + 1. Mako template expansion (on the whole file) + 2. For each line of the result, + + a. Whitespace splitting (using shlex.split()) + b. Brace expansion (using brace_expand()) + c. If the first token is the name of a function, call that function + with the rest of the line as arguments + + * Parsing and execution are *separate* passes - so you can't use the result + of a command in an %if statement (or any other control statements)! + ''' + def __init__(self, fatalerrors=True, templatedir=None, defaults=None, builtins=None): + self.fatalerrors = fatalerrors + self.templatedir = templatedir or "/usr/share/lorax" + self.templatefile = None + self.builtins = builtins or {} + self.defaults = defaults or {} + + +
[docs] def run(self, templatefile, **variables): + for k,v in list(self.defaults.items()) + list(self.builtins.items()): + variables.setdefault(k,v) + logger.debug("executing %s with variables=%s", templatefile, variables) + self.templatefile = templatefile + t = LoraxTemplate(directories=[self.templatedir]) + commands = t.parse(templatefile, variables) + self._run(commands)
+ + + def _run(self, parsed_template): + logger.info("running %s", self.templatefile) + for (num, line) in enumerate(parsed_template,1): + logger.debug("template line %i: %s", num, " ".join(line)) + skiperror = False + (cmd, args) = (line[0], line[1:]) + # Following Makefile convention, if the command is prefixed with + # a dash ('-'), we'll ignore any errors on that line. + if cmd.startswith('-'): + cmd = cmd[1:] + skiperror = True + try: + # grab the method named in cmd and pass it the given arguments + f = getattr(self, cmd, None) + if cmd[0] == '_' or cmd == 'run' or not isinstance(f, collections.Callable): + raise ValueError("unknown command %s" % cmd) + f(*args) + except Exception: # pylint: disable=broad-except + if skiperror: + logger.debug("ignoring error") + continue + logger.error("template command error in %s:", self.templatefile) + logger.error(" %s", " ".join(line)) + # format the exception traceback + exclines = traceback.format_exception(*sys.exc_info()) + # skip the bit about "ltmpl.py, in _run()" - we know that + exclines.pop(1) + # log the "ErrorType: this is what happened" line + logger.error(" %s", exclines[-1].strip()) + # and log the entire traceback to the debug log + for _line in ''.join(exclines).splitlines(): + logger.debug(" %s", _line) + if self.fatalerrors: + raise
+ + +# TODO: operate inside an actual chroot for safety? Not that RPM bothers.. +
[docs]class LoraxTemplateRunner(TemplateRunner): + ''' + This class parses and executes Lorax templates. Sample usage: + + # install a bunch of packages + runner = LoraxTemplateRunner(inroot=rundir, outroot=rundir, dbo=dnf_obj) + runner.run("install-packages.ltmpl") + + # modify a runtime dir + runner = LoraxTemplateRunner(inroot=rundir, outroot=newrun) + runner.run("runtime-transmogrify.ltmpl") + + NOTES: + + * Commands that run external programs (e.g. systemctl) currently use + the *host*'s copy of that program, which may cause problems if there's a + big enough difference between the host and the image you're modifying. + + * The commands are not executed under a real chroot, so absolute symlinks + will point *outside* the inroot/outroot. Be careful with symlinks! + + ADDING NEW COMMANDS: + + * Each template command is just a method of the LoraxTemplateRunner + object - so adding a new command is as easy as adding a new function. + + * Each function gets arguments that correspond to the rest of the tokens + on that line (after word splitting and brace expansion) + + * Commands should raise exceptions for errors - don't use sys.exit() + ''' + def __init__(self, inroot, outroot, dbo=None, fatalerrors=True, + templatedir=None, defaults=None): + self.inroot = inroot + self.outroot = outroot + self.dbo = dbo + builtins = DataHolder(exists=lambda p: rexists(p, root=inroot), + glob=lambda g: list(rglob(g, root=inroot))) + self.results = DataHolder(treeinfo=dict()) # just treeinfo for now + + super(LoraxTemplateRunner, self).__init__(fatalerrors, templatedir, defaults, builtins) + # TODO: set up custom logger with a filter to add line info + + def _out(self, path): + return joinpaths(self.outroot, path) + def _in(self, path): + return joinpaths(self.inroot, path) + + def _filelist(self, *pkgs): + """ Return the list of files in the packages """ + pkglist = [] + for pkg_glob in pkgs: + pkglist += list(self.dbo.sack.query().installed().filter(name__glob=pkg_glob)) + + # dnf/hawkey doesn't make any distinction between file, dir or ghost like yum did + # so only return the files. + return set(f for pkg in pkglist for f in pkg.files if not os.path.isdir(self._out(f))) + + def _getsize(self, *files): + return sum(os.path.getsize(self._out(f)) for f in files if os.path.isfile(self._out(f))) + + def _write_debuginfo_log(self): + """ + Write a list of debuginfo packages to /root/debug-pkgs.log + + If lorax is called with a debug repo find the corresponding debuginfo package + names and write them to /root/debubg-pkgs.log on the boot.iso + """ + for repo in self.dbo.repos: + repo = self.dbo.repos[repo] + if any(True for url in repo.baseurl if "debug" in url): + break + if repo.metalink and "debug" in repo.metalink: + break + if repo.mirrorlist and "debug" in repo.mirrorlist: + break + else: + # No debug repos + return + + available = self.dbo.sack.query().available() + debug_pkgs = [] + for p in list(self.dbo.transaction.install_set): + if available.filter(name=p.name+"-debuginfo"): + debug_pkgs += ["{0.name}-debuginfo-{0.epoch}:{0.version}-{0.release}".format(p)] + + os.makedirs(self._out("root/"), exist_ok=True) + with open(self._out("root/debug-pkgs.log"), "w") as f: + for pkg in debug_pkgs: + f.write("%s\n" % pkg) + +
[docs] def install(self, srcglob, dest): + ''' + install SRC DEST + Copy the given file (or files, if a glob is used) from the input + tree to the given destination in the output tree. + The path to DEST must exist in the output tree. + If DEST is a directory, SRC will be copied into that directory. + If DEST doesn't exist, SRC will be copied to a file with that name, + assuming the rest of the path exists. + This is pretty much like how the 'cp' command works. + + Examples: + install usr/share/myconfig/grub.conf /boot + install /usr/share/myconfig/grub.conf.in /boot/grub.conf + ''' + for src in rglob(self._in(srcglob), fatal=True): + try: + cpfile(src, self._out(dest)) + except shutil.Error as e: + logger.error(e)
+ +
[docs] def installimg(self, *args): + ''' + installimg [--xz|--gzip|--bzip2|--lzma] [-ARG|--ARG=OPTION] SRCDIR DESTFILE + Create a compressed cpio archive of the contents of SRCDIR and place + it in DESTFILE. + + If SRCDIR doesn't exist or is empty nothing is created. + + Examples: + installimg ${LORAXDIR}/product/ images/product.img + installimg ${LORAXDIR}/updates/ images/updates.img + installimg --xz -6 ${LORAXDIR}/updates/ images/updates.img + installimg --xz -9 --memlimit-compress=3700MiB ${LORAXDIR}/updates/ images/updates.img + + Optionally use a different compression type and override the default args + passed to it. The default is xz -9 + ''' + COMPRESSORS = ("--xz", "--gzip", "--bzip2", "--lzma") + if len(args) < 2: + raise ValueError("Not enough args for installimg.") + + srcdir = args[-2] + destfile = args[-1] + if not os.path.isdir(self._in(srcdir)) or not os.listdir(self._in(srcdir)): + return + + compression = "xz" + compressargs = [] + if args[0] in COMPRESSORS: + compression = args[0][2:] + + for arg in args[1:-2]: + if arg.startswith('-'): + compressargs.append(arg) + else: + raise ValueError("Argument is missing -") + + logger.info("Creating image file %s from contents of %s", self._out(destfile), self._in(srcdir)) + logger.debug("Using %s %s compression", compression, compressargs or "") + mkcpio(self._in(srcdir), self._out(destfile), compression=compression, compressargs=compressargs)
+ +
[docs] def mkdir(self, *dirs): + ''' + mkdir DIR [DIR ...] + Create the named DIR(s). Will create leading directories as needed. + + Example: + mkdir /images + ''' + for d in dirs: + d = self._out(d) + if not isdir(d): + os.makedirs(d)
+ +
[docs] def replace(self, pat, repl, *fileglobs): + ''' + replace PATTERN REPLACEMENT FILEGLOB [FILEGLOB ...] + Find-and-replace the given PATTERN (Python-style regex) with the given + REPLACEMENT string for each of the files listed. + + Example: + replace @VERSION@ ${product.version} /boot/grub.conf /boot/isolinux.cfg + ''' + match = False + for g in fileglobs: + for f in rglob(self._out(g)): + match = True + replace(f, pat, repl) + if not match: + raise IOError("no files matched %s" % " ".join(fileglobs))
+ +
[docs] def append(self, filename, data): + ''' + append FILE STRING + Append STRING (followed by a newline character) to FILE. + Python character escape sequences ('\\n', '\\t', etc.) will be + converted to the appropriate characters. + + Examples: + + append /etc/depmod.d/dd.conf "search updates built-in" + append /etc/resolv.conf "" + ''' + with open(self._out(filename), "a") as fobj: + fobj.write(bytes(data, "utf8").decode('unicode_escape')+"\n")
+ +
[docs] def treeinfo(self, section, key, *valuetoks): + ''' + treeinfo SECTION KEY ARG [ARG ...] + Add an item to the treeinfo data store. + The given SECTION will have a new item added where + KEY = ARG ARG ... + + Example: + treeinfo images-${kernel.arch} boot.iso images/boot.iso + ''' + if section not in self.results.treeinfo: + self.results.treeinfo[section] = dict() + self.results.treeinfo[section][key] = " ".join(valuetoks)
+ +
[docs] def installkernel(self, section, src, dest): + ''' + installkernel SECTION SRC DEST + Install the kernel from SRC in the input tree to DEST in the output + tree, and then add an item to the treeinfo data store, in the named + SECTION, where "kernel" = DEST. + + Equivalent to: + install SRC DEST + treeinfo SECTION kernel DEST + ''' + self.install(src, dest) + self.treeinfo(section, "kernel", dest)
+ +
[docs] def installinitrd(self, section, src, dest): + ''' + installinitrd SECTION SRC DEST + Same as installkernel, but for "initrd". + ''' + self.install(src, dest) + self.chmod(dest, '644') + self.treeinfo(section, "initrd", dest)
+ +
[docs] def installupgradeinitrd(self, section, src, dest): + ''' + installupgradeinitrd SECTION SRC DEST + Same as installkernel, but for "upgrade". + ''' + self.install(src, dest) + self.chmod(dest, '644') + self.treeinfo(section, "upgrade", dest)
+ + + + + +
[docs] def copy(self, src, dest): + ''' + copy SRC DEST + Copy SRC to DEST. + If DEST is a directory, SRC will be copied inside it. + If DEST doesn't exist, SRC will be copied to a file with + that name, if the path leading to it exists. + ''' + try: + cpfile(self._out(src), self._out(dest)) + except shutil.Error as e: + logger.error(e)
+ +
[docs] def move(self, src, dest): + ''' + move SRC DEST + Move SRC to DEST. + ''' + mvfile(self._out(src), self._out(dest))
+ +
[docs] def remove(self, *fileglobs): + ''' + remove FILEGLOB [FILEGLOB ...] + Remove all the named files or directories. + Will *not* raise exceptions if the file(s) are not found. + ''' + for g in fileglobs: + for f in rglob(self._out(g)): + remove(f) + logger.debug("removed %s", f)
+ +
[docs] def chmod(self, fileglob, mode): + ''' + chmod FILEGLOB OCTALMODE + Change the mode of all the files matching FILEGLOB to OCTALMODE. + ''' + for f in rglob(self._out(fileglob), fatal=True): + os.chmod(f, int(mode,8))
+ +
[docs] def log(self, msg): + ''' + log MESSAGE + Emit the given log message. Be sure to put it in quotes! + + Example: + log "Reticulating splines, please wait..." + ''' + logger.info(msg)
+ + # TODO: add ssh-keygen, mkisofs(?), find, and other useful commands +
[docs] def runcmd(self, *cmdlist): + ''' + runcmd CMD [ARG ...] + Run the given command with the given arguments. + + NOTE: All paths given MUST be COMPLETE, ABSOLUTE PATHS to the file + or files mentioned. ${root}/${inroot}/${outroot} are good for + constructing these paths. + + FURTHER NOTE: Please use this command only as a last resort! + Whenever possible, you should use the existing template commands. + If the existing commands don't do what you need, fix them! + + Examples: + (this should be replaced with a "find" function) + runcmd find ${root} -name "*.pyo" -type f -delete + %for f in find(root, name="*.pyo"): + remove ${f} + %endfor + ''' + cmd = cmdlist + logger.debug('running command: %s', cmd) + if cmd[0].startswith("--chdir="): + logger.error("--chdir is no longer supported for runcmd.") + raise ValueError("--chdir is no longer supported for runcmd.") + + try: + stdout = runcmd_output(cmd) + if stdout: + logger.debug('command output:\n%s', stdout) + logger.debug("command finished successfully") + except CalledProcessError as e: + if e.output: + logger.error('command output:\n%s', e.output) + logger.error('command returned failure (%d)', e.returncode) + raise
+ +
[docs] def installpkg(self, *pkgs): + ''' + installpkg [--required|--optional] [--except PKGGLOB [--except PKGGLOB ...]] PKGGLOB [PKGGLOB ...] + Request installation of all packages matching the given globs. + Note that this is just a *request* - nothing is *actually* installed + until the 'run_pkg_transaction' command is given. + + --required is now the default. If the PKGGLOB can be missing pass --optional + ''' + if pkgs[0] == '--optional': + pkgs = pkgs[1:] + required = False + elif pkgs[0] == '--required': + pkgs = pkgs[1:] + required = True + else: + required = True + + excludes = [] + while '--except' in pkgs: + idx = pkgs.index('--except') + if len(pkgs) == idx+1: + raise ValueError("installpkg needs an argument after --except") + + excludes.append(pkgs[idx+1]) + pkgs = pkgs[:idx] + pkgs[idx+2:] + + errors = False + for p in pkgs: + try: + # Start by using Subject to generate a package query, which will + # give us a query object similar to what dbo.install would select, + # minus the handling for multilib. This query may contain + # multiple arches. Pull the package names out of that, filter any + # that match the excludes patterns, and pass those names back to + # dbo.install to do the actual, arch and version and multilib + # aware, package selction. + + # dnf queries don't have a concept of negative globs which is why + # the filtering is done the hard way. + + pkgnames = [pkg for pkg in dnf.subject.Subject(p).get_best_query(self.dbo.sack).filter(latest=True)] + if not pkgnames: + raise dnf.exceptions.PackageNotFoundError("no package matched", p) + + # Apply excludes to the name only + for exclude in excludes: + pkgnames = [pkg for pkg in pkgnames if not fnmatch.fnmatch(pkg.name, exclude)] + + # Convert to a sorted NVR list for installation + pkgnvrs = sorted(["{}-{}-{}".format(pkg.name, pkg.version, pkg.release) for pkg in pkgnames]) + + # If the request is a glob, expand it in the log + if any(g for g in ['*','?','.'] if g in p): + logger.info("installpkg: %s expands to %s", p, ",".join(pkgnvrs)) + + for pkgnvr in pkgnvrs: + try: + self.dbo.install(pkgnvr) + except Exception as e: # pylint: disable=broad-except + if required: + raise + # Not required, log it and continue processing pkgs + logger.error("installpkg %s failed: %s", pkgnvr, str(e)) + except Exception as e: # pylint: disable=broad-except + logger.error("installpkg %s failed: %s", p, str(e)) + errors = True + + if errors and required: + raise Exception("Required installpkg failed.")
+ +
[docs] def removepkg(self, *pkgs): + ''' + removepkg PKGGLOB [PKGGLOB...] + Delete the named package(s). + + IMPLEMENTATION NOTES: + RPM scriptlets (%preun/%postun) are *not* run. + Files are deleted, but directories are left behind. + ''' + for p in pkgs: + filepaths = [f.lstrip('/') for f in self._filelist(p)] + # TODO: also remove directories that aren't owned by anything else + if filepaths: + logger.debug("removepkg %s: %ikb", p, self._getsize(*filepaths)/1024) + self.remove(*filepaths) + else: + logger.debug("removepkg %s: no files to remove!", p)
+ +
[docs] def run_pkg_transaction(self): + ''' + run_pkg_transaction + Actually install all the packages requested by previous 'installpkg' + commands. + ''' + try: + logger.info("Checking dependencies") + self.dbo.resolve() + except dnf.exceptions.DepsolveError as e: + logger.error("Dependency check failed: %s", e) + raise + logger.info("%d packages selected", len(self.dbo.transaction)) + if len(self.dbo.transaction) == 0: + raise Exception("No packages in transaction") + + # If a debug repo has been included, write out a list of debuginfo packages + self._write_debuginfo_log() + + pkgs_to_download = self.dbo.transaction.install_set + logger.info("Downloading packages") + progress = LoraxDownloadCallback() + try: + self.dbo.download_packages(pkgs_to_download, progress) + except dnf.exceptions.DownloadError as e: + logger.error("Failed to download the following packages: %s", e) + raise + + logger.info("Preparing transaction from installation source") + try: + display = LoraxRpmCallback() + self.dbo.do_transaction(display=display) + except BaseException as e: + logger.error("The transaction process has ended abruptly: %s", e) + raise + + # Reset the package sack to pick up the installed packages + self.dbo.reset(repos=False) + self.dbo.fill_sack(load_system_repo=True, load_available_repos=False) + + # At this point dnf should know about the installed files. Double check that it really does. + if len(self._filelist("anaconda-core")) == 0: + raise Exception("Failed to reset dbo to installed package set")
+ +
[docs] def removefrom(self, pkg, *globs): + ''' + removefrom PKGGLOB [--allbut] FILEGLOB [FILEGLOB...] + Remove all files matching the given file globs from the package + (or packages) named. + If '--allbut' is used, all the files from the given package(s) will + be removed *except* the ones which match the file globs. + + Examples: + removefrom usbutils /usr/bin/* + removefrom xfsprogs --allbut /sbin/* + ''' + cmd = "%s %s" % (pkg, " ".join(globs)) # save for later logging + keepmatches = False + if globs[0] == '--allbut': + keepmatches = True + globs = globs[1:] + # get pkg filelist and find files that match the globs + filelist = self._filelist(pkg) + matches = set() + for g in globs: + globs_re = re.compile(fnmatch.translate(g)) + m = [f for f in filelist if globs_re.match(f)] + if m: + matches.update(m) + else: + logger.debug("removefrom %s %s: no files matched!", pkg, g) + # are we removing the matches, or keeping only the matches? + if keepmatches: + remove_files = filelist.difference(matches) + else: + remove_files = matches + # remove the files + if remove_files: + logger.debug("removefrom %s: removed %i/%i files, %ikb/%ikb", cmd, + len(remove_files), len(filelist), + self._getsize(*remove_files)/1024, self._getsize(*filelist)/1024) + self.remove(*remove_files) + else: + logger.debug("removefrom %s: no files to remove!", cmd)
+ + # pylint: disable=anomalous-backslash-in-string +
[docs] def removekmod(self, *globs): + ''' + removekmod GLOB [GLOB...] [--allbut] KEEPGLOB [KEEPGLOB...] + Remove all files and directories matching the given file globs from the kernel + modules directory. + + If '--allbut' is used, all the files from the modules will be removed *except* + the ones which match the file globs. There must be at least one initial GLOB + to search and one KEEPGLOB to keep. The KEEPGLOB is expanded to be *KEEPGLOB* + so that it will match anywhere in the path. + + This only removes files from under /lib/modules/\*/kernel/ + + Examples: + removekmod sound drivers/media drivers/hwmon drivers/video + removekmod drivers/char --allbut virtio_console hw_random + ''' + cmd = " ".join(globs) + if "--allbut" in globs: + idx = globs.index("--allbut") + if idx == 0: + raise ValueError("removekmod needs at least one GLOB before --allbut") + + # Apply keepglobs anywhere they appear in the path + keepglobs = globs[idx+1:] + if len(keepglobs) == 0: + raise ValueError("removekmod needs at least one GLOB after --allbut") + + globs = globs[:idx] + else: + # Nothing to keep + keepglobs = [] + + filelist = set() + for g in globs: + for top_dir in rglob(self._out("/lib/modules/*/kernel/"+g)): + for root, _dirs, files in os.walk(top_dir): + filelist.update(root+"/"+f for f in files) + + # Remove anything matching keepglobs from the list + matches = set() + for g in keepglobs: + globs_re = re.compile(fnmatch.translate("*"+g+"*")) + m = [f for f in filelist if globs_re.match(f)] + if m: + matches.update(m) + else: + logger.debug("removekmod %s: no files matched!", g) + remove_files = filelist.difference(matches) + + if remove_files: + logger.debug("removekmod: removing %d files", len(remove_files)) + list(remove(f) for f in remove_files) + else: + logger.debug("removekmod %s: no files to remove!", cmd)
+ +
[docs] def createaddrsize(self, addr, src, dest): + ''' + createaddrsize INITRD_ADDRESS INITRD ADDRSIZE + Create the initrd.addrsize file required in LPAR boot process. + + Examples: + createaddrsize ${INITRD_ADDRESS} ${outroot}/${BOOTDIR}/initrd.img ${outroot}/${BOOTDIR}/initrd.addrsize + ''' + addrsize = open(dest, "wb") + addrsize_data = struct.pack(">iiii", 0, int(addr, 16), 0, os.stat(src).st_size) + addrsize.write(addrsize_data) + addrsize.close()
+ +
[docs] def systemctl(self, cmd, *units): + ''' + systemctl [enable|disable|mask] UNIT [UNIT...] + Enable, disable, or mask the given systemd units. + + Examples: + systemctl disable lvm2-monitor.service + systemctl mask fedora-storage-init.service fedora-configure.service + ''' + if cmd not in ('enable', 'disable', 'mask'): + raise ValueError('unsupported systemctl cmd: %s' % cmd) + if not units: + logger.debug("systemctl: no units given for %s, ignoring", cmd) + return + self.mkdir("/run/systemd/system") # XXX workaround for systemctl bug + systemctl = ['systemctl', '--root', self.outroot, '--no-reload', cmd] + # When a unit doesn't exist systemd aborts the command. Run them one at a time. + # XXX for some reason 'systemctl enable/disable' always returns 1 + for unit in units: + try: + cmd = systemctl + [unit] + runcmd(cmd) + except CalledProcessError: + pass
+ +
[docs]class LiveTemplateRunner(TemplateRunner): + """ + This class parses and executes a limited Lorax template. Sample usage: + + # install a bunch of packages + runner = LiveTemplateRunner(dbo, templatedir, defaults) + runner.run("live-install.tmpl") + + It is meant to be used with the live-install.tmpl which lists the per-arch + pacages needed to build the live-iso output. + """ + def __init__(self, dbo, fatalerrors=True, templatedir=None, defaults=None): + self.dbo = dbo + self.pkgs = [] + self.pkgnames = [] + + super(LiveTemplateRunner, self).__init__(fatalerrors, templatedir, defaults) + +
[docs] def installpkg(self, *pkgs): + ''' + installpkg [--required|--optional] [--except PKGGLOB [--except PKGGLOB ...]] PKGGLOB [PKGGLOB ...] + Request installation of all packages matching the given globs. + Note that this is just a *request* - nothing is *actually* installed + until the 'run_pkg_transaction' command is given. + + --required is now the default. If the PKGGLOB can be missing pass --optional + ''' + if pkgs[0] == '--optional': + pkgs = pkgs[1:] + required = False + elif pkgs[0] == '--required': + pkgs = pkgs[1:] + required = True + else: + required = True + + excludes = [] + while '--except' in pkgs: + idx = pkgs.index('--except') + if len(pkgs) == idx+1: + raise ValueError("installpkg needs an argument after --except") + + excludes.append(pkgs[idx+1]) + pkgs = pkgs[:idx] + pkgs[idx+2:] + + errors = False + for p in pkgs: + try: + # Start by using Subject to generate a package query, which will + # give us a query object similar to what dbo.install would select, + # minus the handling for multilib. This query may contain + # multiple arches. Pull the package names out of that, filter any + # that match the excludes patterns, and pass those names back to + # dbo.install to do the actual, arch and version and multilib + # aware, package selction. + + # dnf queries don't have a concept of negative globs which is why + # the filtering is done the hard way. + + pkgnames = [pkg for pkg in dnf.subject.Subject(p).get_best_query(self.dbo.sack).filter(latest=True)] + if not pkgnames: + raise dnf.exceptions.PackageNotFoundError("no package matched", p) + + # Apply excludes to the name only + for exclude in excludes: + pkgnames = [pkg for pkg in pkgnames if not fnmatch.fnmatch(pkg.name, exclude)] + + # Convert to a sorted NVR list for installation + pkgnvrs = sorted(["{}-{}-{}".format(pkg.name, pkg.version, pkg.release) for pkg in pkgnames]) + + # If the request is a glob, expand it in the log + if any(g for g in ['*','?','.'] if g in p): + logger.info("installpkg: %s expands to %s", p, ",".join(pkgnvrs)) + + self.pkgs.extend(pkgnvrs) + self.pkgnames.extend([pkg.name for pkg in pkgnames]) + except Exception as e: # pylint: disable=broad-except + logger.error("installpkg %s failed: %s", p, str(e)) + errors = True + + if errors and required: + raise Exception("Required installpkg failed.")
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/monitor.html b/f29-branch/_modules/pylorax/monitor.html new file mode 100644 index 00000000..74e51278 --- /dev/null +++ b/f29-branch/_modules/pylorax/monitor.html @@ -0,0 +1,420 @@ + + + + + + + + + + + pylorax.monitor — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.monitor

+# monitor.py
+#
+# Copyright (C) 2011-2015  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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Brian C. Lane <bcl@redhat.com>
+#
+import logging
+log = logging.getLogger("livemedia-creator")
+
+import re
+import socket
+import socketserver
+import threading
+import time
+
+
[docs]class LogRequestHandler(socketserver.BaseRequestHandler): + """ + Handle monitoring and saving the logfiles from the virtual install + + Incoming data is written to self.server.log_path and each line is checked + for patterns that would indicate that the installation failed. + self.server.log_error is set True when this happens. + """ + + simple_tests = [ + "Traceback (", + "traceback script(s) have been run", + "Out of memory:", + "Call Trace:", + "insufficient disk space:", + "Not enough disk space to download the packages", + "error populating transaction after", + "crashed on signal", + "packaging: Missed: NoSuchPackage", + "packaging: Installation failed", + "The following error occurred while installing. This is a fatal error" + ] + + re_tests = [ + r"packaging: base repo .* not valid", + r"packaging: .* requires .*" + ] + +
[docs] def setup(self): + """Start writing to self.server.log_path""" + + if self.server.log_path: + self.fp = open(self.server.log_path, "w") # pylint: disable=attribute-defined-outside-init + else: + self.fp = None + self.request.settimeout(10)
+ +
[docs] def handle(self): + """ + Write incoming data to a logfile and check for errors + + Split incoming data into lines and check for any Tracebacks or other + errors that indicate that the install failed. + + Loops until self.server.kill is True + """ + log.info("Processing logs from %s", self.client_address) + line = "" + while True: + if self.server.kill: + break + + try: + data = str(self.request.recv(4096), "utf8") + if self.fp: + self.fp.write(data) + self.fp.flush() + + # check the data for errors and set error flag + # need to assemble it into lines so we can test for the error + # string. + while data: + more = data.split("\n", 1) + line += more[0] + if len(more) > 1: + self.iserror(line) + line = "" + data = more[1] + else: + data = None + + except socket.timeout: + pass + except Exception as e: # pylint: disable=broad-except + log.info("log processing killed by exception: %s", e) + break
+ +
[docs] def finish(self): + log.info("Shutting down log processing") + self.request.close() + if self.fp: + self.fp.close()
+ +
[docs] def iserror(self, line): + """ + Check a line to see if it contains an error indicating installation failure + + :param str line: log line to check for failure + + If the line contains IGNORED it will be skipped. + """ + if "IGNORED" in line: + return + + for t in self.simple_tests: + if t in line: + self.server.log_error = True + self.server.error_line = line + return + for t in self.re_tests: + if re.search(t, line): + self.server.log_error = True + self.server.error_line = line + return
+ + +
[docs]class LogServer(socketserver.TCPServer): + """A TCP Server that listens for log data""" + + # Number of seconds to wait for a connection after startup + timeout = 60 + + def __init__(self, log_path, *args, **kwargs): + """ + Setup the log server + + :param str log_path: Path to the log file to write + """ + self.kill = False + self.log_error = False + self.error_line = "" + self.log_path = log_path + self._timeout = kwargs.pop("timeout", None) + if self._timeout: + self._start_time = time.time() + socketserver.TCPServer.__init__(self, *args, **kwargs) + +
[docs] def log_check(self): + """ + Check to see if an error has been found in the log + + :returns: True if there has been an error + :rtype: bool + """ + if self._timeout: + taking_too_long = time.time() > self._start_time + (self._timeout * 60) + if taking_too_long: + log.error("Canceling installation due to timeout") + else: + taking_too_long = False + return self.log_error or taking_too_long
+ + +
[docs]class LogMonitor(object): + """ + Setup a server to monitor the logs output by the installation + + This needs to be running before the virt-install runs, it expects + there to be a listener on the port used for the virtio log port. + """ + def __init__(self, log_path=None, host="localhost", port=0, timeout=None, log_request_handler_class=LogRequestHandler): + """ + Start a thread to monitor the logs. + + :param str log_path: Path to the logfile to write + :param str host: Host to bind to. Default is localhost. + :param int port: Port to listen to or 0 to pick a port + + If 0 is passed for the port the dynamically assigned port will be + available as self.port + + If log_path isn't set then it only monitors the logs, instead of + also writing them to disk. + """ + self.server = LogServer(log_path, (host, port), log_request_handler_class, timeout=timeout) + self.host, self.port = self.server.server_address + self.log_path = log_path + self.server_thread = threading.Thread(target=self.server.handle_request) + self.server_thread.daemon = True + self.server_thread.start() + +
[docs] def shutdown(self): + """Force shutdown of the monitoring thread""" + self.server.kill = True + self.server_thread.join()
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/mount.html b/f29-branch/_modules/pylorax/mount.html new file mode 100644 index 00000000..1b543e83 --- /dev/null +++ b/f29-branch/_modules/pylorax/mount.html @@ -0,0 +1,319 @@ + + + + + + + + + + + pylorax.mount — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.mount

+# mount.py
+#
+# Copyright (C) 2011-2015  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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s): Brian C. Lane <bcl@redhat.com>
+#
+import logging
+log = logging.getLogger("livemedia-creator")
+
+import os
+
+from pylorax.imgutils import mount, umount
+from pylorax.executils import execWithCapture
+
+
[docs]class IsoMountpoint(object): + """ + Mount the iso and check to make sure the vmlinuz and initrd.img files exist + + Also check the iso for a a stage2 image and set a flag and extract the + iso's label. + + stage2 can be either LiveOS/squashfs.img or images/install.img + """ + def __init__(self, iso_path, initrd_path=None): + """ + Mount the iso + + :param str iso_path: Path to the iso to mount + :param str initrd_path: Optional path to initrd + + initrd_path can be used to point to a tree with a newer + initrd.img than the iso has. The iso is still used for stage2. + + self.kernel and self.initrd point to the kernel and initrd. + self.stage2 is set to True if there is a stage2 image. + self.repo is the path to the mounted iso if there is a /repodata dir. + """ + self.label = None + self.iso_path = iso_path + self.initrd_path = initrd_path + + if not self.initrd_path: + self.mount_dir = mount(self.iso_path, opts="loop") + else: + self.mount_dir = self.initrd_path + + kernel_list = [("/isolinux/vmlinuz", "/isolinux/initrd.img"), + ("/ppc/ppc64/vmlinuz", "/ppc/ppc64/initrd.img")] + + if os.path.isdir(self.mount_dir+"/repodata"): + self.repo = self.mount_dir + else: + self.repo = None + self.stage2 = os.path.exists(self.mount_dir+"/LiveOS/squashfs.img") or \ + os.path.exists(self.mount_dir+"/images/install.img") + + try: + for kernel, initrd in kernel_list: + if (os.path.isfile(self.mount_dir+kernel) and + os.path.isfile(self.mount_dir+initrd)): + self.kernel = self.mount_dir+kernel + self.initrd = self.mount_dir+initrd + break + else: + raise Exception("Missing kernel and initrd file in iso, failed" + " to search under: {0}".format(kernel_list)) + except: + self.umount() + raise + + self.get_iso_label() + +
[docs] def umount( self ): + """Unmount the iso""" + if not self.initrd_path: + umount(self.mount_dir)
+ +
[docs] def get_iso_label(self): + """ + Get the iso's label using isoinfo + + Sets self.label if one is found + """ + isoinfo_output = execWithCapture("isoinfo", ["-d", "-i", self.iso_path]) + log.debug(isoinfo_output) + for line in isoinfo_output.splitlines(): + if line.startswith("Volume id: "): + self.label = line[11:] + return
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/sysutils.html b/f29-branch/_modules/pylorax/sysutils.html new file mode 100644 index 00000000..097f63c4 --- /dev/null +++ b/f29-branch/_modules/pylorax/sysutils.html @@ -0,0 +1,349 @@ + + + + + + + + + + + pylorax.sysutils — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.sysutils

+#
+# sysutils.py
+#
+# Copyright (C) 2009-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#
+
+__all__ = ["joinpaths", "touch", "replace", "chown_", "chmod_", "remove",
+           "linktree"]
+
+import sys
+import os
+import re
+import fileinput
+import pwd
+import grp
+import glob
+import shutil
+import shlex
+from configparser import ConfigParser
+
+from pylorax.executils import runcmd
+
+
[docs]def joinpaths(*args, **kwargs): + path = os.path.sep.join(args) + + if kwargs.get("follow_symlinks"): + return os.path.realpath(path) + else: + return path
+ + +
[docs]def touch(fname): + # python closes the file when it goes out of scope + open(fname, "w").write("")
+ + +
[docs]def replace(fname, find, sub): + fin = fileinput.input(fname, inplace=1) + pattern = re.compile(find) + + for line in fin: + line = pattern.sub(sub, line) + sys.stdout.write(line) + + fin.close()
+ + +
[docs]def chown_(path, user=None, group=None, recursive=False): + uid = gid = -1 + + if user is not None: + uid = pwd.getpwnam(user)[2] + if group is not None: + gid = grp.getgrnam(group)[2] + + for fname in glob.iglob(path): + os.chown(fname, uid, gid) + + if recursive and os.path.isdir(fname): + for nested in os.listdir(fname): + nested = joinpaths(fname, nested) + chown_(nested, user, group, recursive)
+ + +
[docs]def chmod_(path, mode, recursive=False): + for fname in glob.iglob(path): + os.chmod(fname, mode) + + if recursive and os.path.isdir(fname): + for nested in os.listdir(fname): + nested = joinpaths(fname, nested) + chmod_(nested, mode, recursive)
+ + +def cpfile(src, dst): + shutil.copy2(src, dst) + if os.path.isdir(dst): + dst = joinpaths(dst, os.path.basename(src)) + + return dst + +def mvfile(src, dst): + if os.path.isdir(dst): + dst = joinpaths(dst, os.path.basename(src)) + os.rename(src, dst) + return dst + +
[docs]def remove(target): + if os.path.isdir(target) and not os.path.islink(target): + shutil.rmtree(target) + else: + os.unlink(target)
+ +
[docs]def linktree(src, dst): + runcmd(["/bin/cp", "-alx", src, dst])
+ +def unquote(s): + return ' '.join(shlex.split(s)) + +class UnquotingConfigParser(ConfigParser): + """A ConfigParser, only with unquoting of the values.""" + # pylint: disable=arguments-differ + def get(self, *args, **kwargs): + ret = super().get(*args, **kwargs) + if ret: + ret = unquote(ret) + return ret + +def flatconfig(filename): + """Use UnquotingConfigParser to read a flat config file (without + section headers) by adding a section header. + """ + with open (filename, 'r') as conffh: + conftext = "[main]\n" + conffh.read() + config = UnquotingConfigParser() + config.read_string(conftext) + return config['main'] +
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/treebuilder.html b/f29-branch/_modules/pylorax/treebuilder.html new file mode 100644 index 00000000..5ba41364 --- /dev/null +++ b/f29-branch/_modules/pylorax/treebuilder.html @@ -0,0 +1,628 @@ + + + + + + + + + + + pylorax.treebuilder — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.treebuilder

+# treebuilder.py - handle arch-specific tree building stuff using templates
+#
+# Copyright (C) 2011-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Author(s):  Will Woods <wwoods@redhat.com>
+
+import logging
+logger = logging.getLogger("pylorax.treebuilder")
+
+import os, re
+from os.path import basename
+from shutil import copytree, copy2
+from pathlib import Path
+import itertools
+
+from pylorax.sysutils import joinpaths, remove
+from pylorax.base import DataHolder
+from pylorax.ltmpl import LoraxTemplateRunner
+import pylorax.imgutils as imgutils
+from pylorax.executils import runcmd, runcmd_output, execWithCapture
+
+templatemap = {
+    'i386':    'x86.tmpl',
+    'x86_64':  'x86.tmpl',
+    'ppc':     'ppc.tmpl',
+    'ppc64':   'ppc.tmpl',
+    'ppc64le': 'ppc64le.tmpl',
+    's390':    's390.tmpl',
+    's390x':   's390.tmpl',
+    'aarch64': 'aarch64.tmpl',
+    'arm':     'arm.tmpl',
+    'armhfp':  'arm.tmpl',
+}
+
+
[docs]def generate_module_info(moddir, outfile=None): + def module_desc(mod): + output = runcmd_output(["modinfo", "-F", "description", mod]) + return output.strip() + def read_module_set(name): + return set(l.strip() for l in open(joinpaths(moddir,name)) if ".ko" in l) + modsets = {'scsi':read_module_set("modules.block"), + 'eth':read_module_set("modules.networking")} + + modinfo = list() + for root, _dirs, files in os.walk(moddir): + for modtype, modset in modsets.items(): + for mod in modset.intersection(files): # modules in this dir + (name, _ext) = os.path.splitext(mod) # foo.ko -> (foo, .ko) + desc = module_desc(joinpaths(root,mod)) or "%s driver" % name + modinfo.append(dict(name=name, type=modtype, desc=desc)) + + out = open(outfile or joinpaths(moddir,"module-info"), "w") + out.write("Version 0\n") + for mod in sorted(modinfo, key=lambda m: m.get('name')): + out.write('{name}\n\t{type}\n\t"{desc:.65}"\n'.format(**mod))
+ +
[docs]class RuntimeBuilder(object): + '''Builds the anaconda runtime image.''' + def __init__(self, product, arch, dbo, templatedir=None, + installpkgs=None, excludepkgs=None, + add_templates=None, + add_template_vars=None): + root = dbo.conf.installroot + # use a copy of product so we can modify it locally + product = product.copy() + product.name = product.name.lower() + self.vars = DataHolder(arch=arch, product=product, dbo=dbo, root=root, + basearch=arch.basearch, libdir=arch.libdir) + self.dbo = dbo + self._runner = LoraxTemplateRunner(inroot=root, outroot=root, + dbo=dbo, templatedir=templatedir) + self.add_templates = add_templates or [] + self.add_template_vars = add_template_vars or {} + self._installpkgs = installpkgs or [] + self._excludepkgs = excludepkgs or [] + self._runner.defaults = self.vars + self.dbo.reset() + + def _install_branding(self): + release = None + q = self.dbo.sack.query() + a = q.available() + for pkg in a.filter(provides='system-release'): + logger.debug("Found release package %s", pkg) + if pkg.name.startswith('generic'): + continue + else: + release = pkg.name + break + + if not release: + logger.error('could not get the release') + return + + # release + logger.info('got release: %s', release) + self._runner.installpkg(release) + + # logos + release, _suffix = release.split('-', 1) + self._runner.installpkg('%s-logos' % release) + +
[docs] def install(self): + '''Install packages and do initial setup with runtime-install.tmpl''' + self._install_branding() + if len(self._installpkgs) > 0: + self._runner.installpkg(*self._installpkgs) + if len(self._excludepkgs) > 0: + self._runner.removepkg(*self._excludepkgs) + self._runner.run("runtime-install.tmpl") + for tmpl in self.add_templates: + self._runner.run(tmpl, **self.add_template_vars)
+ +
[docs] def writepkglists(self, pkglistdir): + '''debugging data: write out lists of package contents''' + if not os.path.isdir(pkglistdir): + os.makedirs(pkglistdir) + q = self.dbo.sack.query() + for pkgobj in q.installed(): + with open(joinpaths(pkglistdir, pkgobj.name), "w") as fobj: + for fname in pkgobj.files: + fobj.write("{0}\n".format(fname))
+ +
[docs] def postinstall(self): + '''Do some post-install setup work with runtime-postinstall.tmpl''' + # copy configdir into runtime root beforehand + configdir = joinpaths(self._runner.templatedir,"config_files") + configdir_path = "tmp/config_files" + fullpath = joinpaths(self.vars.root, configdir_path) + if os.path.exists(fullpath): + remove(fullpath) + copytree(configdir, fullpath) + self._runner.run("runtime-postinstall.tmpl", configdir=configdir_path)
+ +
[docs] def cleanup(self): + '''Remove unneeded packages and files with runtime-cleanup.tmpl''' + self._runner.run("runtime-cleanup.tmpl")
+ +
[docs] def verify(self): + '''Ensure that contents of the installroot can run''' + status = True + + ELF_MAGIC = b'\x7fELF' + + # Iterate over all files in /usr/bin and /usr/sbin + # For ELF files, gather them into a list and we'll check them all at + # the end. For files with a #!, check them as we go + elf_files = [] + usr_bin = Path(self.vars.root + '/usr/bin') + usr_sbin = Path(self.vars.root + '/usr/sbin') + for path in (str(x) for x in itertools.chain(usr_bin.iterdir(), usr_sbin.iterdir()) \ + if x.is_file()): + with open(path, "rb") as f: + magic = f.read(4) + if magic == ELF_MAGIC: + # Save the path, minus the chroot prefix + elf_files.append(path[len(self.vars.root):]) + elif magic[:2] == b'#!': + # Reopen the file as text and read the first line. + # Open as latin-1 so that stray 8-bit characters don't make + # things blow up. We only really care about ASCII parts. + with open(path, "rt", encoding="latin-1") as f_text: + # Remove the #!, split on space, and take the first part + shabang = f_text.readline()[2:].split()[0] + + # Does the path exist? + if not os.path.exists(self.vars.root + shabang): + logger.error('%s, needed by %s, does not exist', shabang, path) + status = False + + # Now, run ldd on all the ELF files + # Just run ldd once on everything so it isn't logged a million times. + # At least one thing in the list isn't going to be a dynamic executable, + # so use execWithCapture to ignore the exit code. + filename = '' + for line in execWithCapture('ldd', elf_files, root=self.vars.root, + log_output=False, filter_stderr=True).split('\n'): + if line and not line[0].isspace(): + # New filename header, strip the : at the end and save + filename = line[:-1] + elif 'not found' in line: + logger.error('%s, needed by %s, not found', line.split()[0], filename) + status = False + + return status
+ +
[docs] def writepkgsizes(self, pkgsizefile): + '''debugging data: write a big list of pkg sizes''' + fobj = open(pkgsizefile, "w") + getsize = lambda f: os.lstat(f).st_size if os.path.exists(f) else 0 + q = self.dbo.sack.query() + for p in sorted(q.installed()): + pkgsize = sum(getsize(joinpaths(self.vars.root,f)) for f in p.files) + fobj.write("{0.name}.{0.arch}: {1}\n".format(p, pkgsize))
+ +
[docs] def generate_module_data(self): + root = self.vars.root + moddir = joinpaths(root, "lib/modules/") + for kernel in findkernels(root=root): + ksyms = joinpaths(root, "boot/System.map-%s" % kernel.version) + logger.info("doing depmod and module-info for %s", kernel.version) + runcmd(["depmod", "-a", "-F", ksyms, "-b", root, kernel.version]) + generate_module_info(moddir+kernel.version, outfile=moddir+"module-info")
+ +
[docs] def create_squashfs_runtime(self, outfile="/var/tmp/squashfs.img", compression="xz", compressargs=None, size=2): + """Create a plain squashfs runtime""" + compressargs = compressargs or [] + os.makedirs(os.path.dirname(outfile)) + + # squash the rootfs + imgutils.mksquashfs(self.vars.root, outfile, compression, compressargs)
+ +
[docs] def create_ext4_runtime(self, outfile="/var/tmp/squashfs.img", compression="xz", compressargs=None, size=2): + """Create a squashfs compressed ext4 runtime""" + # make live rootfs image - must be named "LiveOS/rootfs.img" for dracut + compressargs = compressargs or [] + workdir = joinpaths(os.path.dirname(outfile), "runtime-workdir") + os.makedirs(joinpaths(workdir, "LiveOS")) + + imgutils.mkrootfsimg(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), + "Anaconda", size=size) + + # squash the live rootfs and clean up workdir + imgutils.mksquashfs(workdir, outfile, compression, compressargs) + remove(workdir)
+ +
[docs] def finished(self): + """ Done using RuntimeBuilder + + Close the dnf base object + """ + self.dbo.close()
+ +
[docs]class TreeBuilder(object): + '''Builds the arch-specific boot images. + inroot should be the installtree root (the newly-built runtime dir)''' + def __init__(self, product, arch, inroot, outroot, runtime, isolabel, domacboot=True, doupgrade=True, + templatedir=None, add_templates=None, add_template_vars=None, workdir=None, extra_boot_args=""): + + # NOTE: if you pass an arg named "runtime" to a mako template it'll + # clobber some mako internal variables - hence "runtime_img". + self.vars = DataHolder(arch=arch, product=product, runtime_img=runtime, + runtime_base=basename(runtime), + inroot=inroot, outroot=outroot, + basearch=arch.basearch, libdir=arch.libdir, + isolabel=isolabel, udev=udev_escape, domacboot=domacboot, doupgrade=doupgrade, + workdir=workdir, lower=string_lower, + extra_boot_args=extra_boot_args) + self._runner = LoraxTemplateRunner(inroot, outroot, templatedir=templatedir) + self._runner.defaults = self.vars + self.add_templates = add_templates or [] + self.add_template_vars = add_template_vars or {} + self.templatedir = templatedir + self.treeinfo_data = None + + @property + def kernels(self): + return findkernels(root=self.vars.inroot) + +
[docs] def rebuild_initrds(self, add_args=None, backup="", prefix=""): + '''Rebuild all the initrds in the tree. If backup is specified, each + initrd will be renamed with backup as a suffix before rebuilding. + If backup is empty, the existing initrd files will be overwritten. + If suffix is specified, the existing initrd is untouched and a new + image is built with the filename "${prefix}-${kernel.version}.img" + + If the initrd doesn't exist its name will be created based on the + name of the kernel. + ''' + add_args = add_args or [] + dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + add_args + if not backup: + dracut.append("--force") + + if not self.kernels: + raise Exception("No kernels found, cannot rebuild_initrds") + + # Hush some dracut warnings. TODO: bind-mount proc in place? + open(joinpaths(self.vars.inroot,"/proc/modules"),"w") + for kernel in self.kernels: + if prefix: + idir = os.path.dirname(kernel.path) + outfile = joinpaths(idir, prefix+'-'+kernel.version+'.img') + elif hasattr(kernel, "initrd"): + # If there is an existing initrd, use that + outfile = kernel.initrd.path + else: + # Construct an initrd from the kernel name + outfile = kernel.path.replace("vmlinuz-", "initrd-") + ".img" + logger.info("rebuilding %s", outfile) + if backup: + initrd = joinpaths(self.vars.inroot, outfile) + if os.path.exists(initrd): + os.rename(initrd, initrd + backup) + cmd = dracut + [outfile, kernel.version] + runcmd(cmd, root=self.vars.inroot) + + # ppc64 cannot boot images > 32MiB, check size and warn + if self.vars.arch.basearch in ("ppc64", "ppc64le") and os.path.exists(outfile): + st = os.stat(outfile) + if st.st_size > 32 * 1024 * 1024: + logging.warning("ppc64 initrd %s is > 32MiB", outfile) + + os.unlink(joinpaths(self.vars.inroot,"/proc/modules"))
+ +
[docs] def build(self): + templatefile = templatemap[self.vars.arch.basearch] + for tmpl in self.add_templates: + self._runner.run(tmpl, **self.add_template_vars) + self._runner.run(templatefile, kernels=self.kernels) + self.treeinfo_data = self._runner.results.treeinfo + self.implantisomd5()
+ +
[docs] def implantisomd5(self): + for _section, data in self.treeinfo_data.items(): + if 'boot.iso' in data: + iso = joinpaths(self.vars.outroot, data['boot.iso']) + runcmd(["implantisomd5", iso])
+ + @property + def dracut_hooks_path(self): + """ Return the path to the lorax dracut hooks scripts + + Use the configured share dir if it is setup, + otherwise default to /usr/share/lorax/dracut_hooks + """ + if self.templatedir: + return joinpaths(self.templatedir, "dracut_hooks") + else: + return "/usr/share/lorax/dracut_hooks" + +
[docs] def copy_dracut_hooks(self, hooks): + """ Copy the hook scripts in hooks into the installroot's /tmp/ + and return a list of commands to pass to dracut when creating the + initramfs + + hooks is a list of tuples with the name of the hook script and the + target dracut hook directory + (eg. [("99anaconda-copy-ks.sh", "/lib/dracut/hooks/pre-pivot")]) + """ + dracut_commands = [] + for hook_script, dracut_path in hooks: + src = joinpaths(self.dracut_hooks_path, hook_script) + if not os.path.exists(src): + logger.error("Missing lorax dracut hook script %s", (src)) + continue + dst = joinpaths(self.vars.inroot, "/tmp/", hook_script) + copy2(src, dst) + dracut_commands += ["--include", joinpaths("/tmp/", hook_script), + dracut_path] + return dracut_commands
+ +#### TreeBuilder helper functions + +
[docs]def findkernels(root="/", kdir="boot"): + # To find possible flavors, awk '/BuildKernel/ { print $4 }' kernel.spec + flavors = ('debug', 'PAE', 'PAEdebug', 'smp', 'xen', 'lpae') + kre = re.compile(r"vmlinuz-(?P<version>.+?\.(?P<arch>[a-z0-9_]+)" + r"(.(?P<flavor>{0}))?)$".format("|".join(flavors))) + kernels = [] + bootfiles = os.listdir(joinpaths(root, kdir)) + for f in bootfiles: + match = kre.match(f) + if match: + kernel = DataHolder(path=joinpaths(kdir, f)) + kernel.update(match.groupdict()) # sets version, arch, flavor + kernels.append(kernel) + + # look for associated initrd/initramfs/etc. + for kernel in kernels: + for f in bootfiles: + if f.endswith('-'+kernel.version+'.img'): + imgtype, _rest = f.split('-',1) + # special backwards-compat case + if imgtype == 'initramfs': + imgtype = 'initrd' + kernel[imgtype] = DataHolder(path=joinpaths(kdir, f)) + + logger.debug("kernels=%s", kernels) + return kernels
+ +# udev whitelist: 'a-zA-Z0-9#+.:=@_-' (see is_whitelisted in libudev-util.c) +udev_blacklist=' !"$%&\'()*,/;<>?[\\]^`{|}~' # ASCII printable, minus whitelist +udev_blacklist += ''.join(chr(i) for i in range(32)) # ASCII non-printable +
[docs]def udev_escape(label): + out = '' + for ch in label: + out += ch if ch not in udev_blacklist else '\\x%02x' % ord(ch) + return out
+ +
[docs]def string_lower(string): + """ Return a lowercase string. + + :param string: String to lowercase + + This is used as a filter in the templates. + """ + return string.lower()
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_modules/pylorax/treeinfo.html b/f29-branch/_modules/pylorax/treeinfo.html new file mode 100644 index 00000000..38589218 --- /dev/null +++ b/f29-branch/_modules/pylorax/treeinfo.html @@ -0,0 +1,280 @@ + + + + + + + + + + + pylorax.treeinfo — Lorax 29.28 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.treeinfo

+#
+# treeinfo.py
+#
+# Copyright (C) 2010-2015 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, see <http://www.gnu.org/licenses/>.
+#
+# Red Hat Author(s):  Martin Gracik <mgracik@redhat.com>
+#
+
+import logging
+logger = logging.getLogger("pylorax.treeinfo")
+
+import configparser
+import os
+import time
+
+
+
[docs]class TreeInfo(object): + + def __init__(self, product, version, variant, basearch, + packagedir=""): + + self.c = configparser.ConfigParser() + + if 'SOURCE_DATE_EPOCH' in os.environ: + timestamp = os.environ['SOURCE_DATE_EPOCH'] + else: + timestamp = str(time.time()) + + section = "general" + data = {"timestamp": timestamp, + "family": product, + "version": version, + "name": "%s-%s" % (product, version), + "variant": variant or "", + "arch": basearch, + "packagedir": packagedir} + + self.c.add_section(section) + list(self.c.set(section, key, value) for key, value in data.items()) + +
[docs] def add_section(self, section, data): + if not self.c.has_section(section): + self.c.add_section(section) + + list(self.c.set(section, key, value) for key, value in data.items())
+ +
[docs] def write(self, outfile): + logger.info("writing .treeinfo file") + with open(outfile, "w") as fobj: + self.c.write(fobj)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f29-branch/_sources/composer-cli.rst.txt b/f29-branch/_sources/composer-cli.rst.txt new file mode 100644 index 00000000..a67f9c10 --- /dev/null +++ b/f29-branch/_sources/composer-cli.rst.txt @@ -0,0 +1,63 @@ +composer-cli +============ + +:Authors: + Brian C. Lane + +``composer-cli`` is used to interact with the ``lorax-composer`` API server, managing blueprints, exploring available packages, and building new images. + +It requires `lorax-composer `_ to be installed on the +local system, and the user running it needs to be a member of the ``weldr`` +group. They do not need to be root, but all of the `security precautions +`_ apply. + +composer-cli cmdline arguments +------------------------------ + +.. argparse:: + :ref: composer.cli.cmdline.composer_cli_parser + :prog: composer-cli + +Edit a Blueprint +---------------- + +Start out by listing the available blueprints using ``composer-cli blueprints +list``, pick one and save it to the local directory by running ``composer-cli +blueprints save http-server``. If there are no blueprints available you can +copy one of the examples `from the test suite +`_. + +Edit the file (it will be saved with a .toml extension) and change the +description, add a package or module to it. Send it back to the server by +running ``composer-cli blueprints push http-server.toml``. You can verify that it was +saved by viewing the changelog - ``composer-cli blueprints changes http-server``. + +Build an image +---------------- + +Build a ``qcow2`` disk image from this blueprint by running ``composer-cli +compose start http-server qcow2``. It will print a UUID that you can use to +keep track of the build. You can also cancel the build if needed. + +<<<<<<< HEAD +The available types of images is displayed by ``composer-cli compose types``. +Currently this consists of: alibaba, ami, ext4-filesystem, google, hyper-v, +live-iso, openstack, partitioned-disk, qcow2, tar, vhd, vmdk + +Monitor the build status +------------------------ + +Monitor it using ``composer-cli compose status``, which will show the status of +all the builds on the system. You can view the end of the anaconda build logs +once it is in the ``RUNNING`` state using ``composer-cli compose log UUID`` +where UUID is the UUID returned by the start command. + +Once the build is in the ``FINISHED`` state you can download the image. + +Download the image +------------------ + +Downloading the final image is done with ``composer-cli compose image UUID`` and it will +save the qcow2 image as ``UUID-disk.qcow2`` which you can then use to boot a VM like this:: + + qemu-kvm --name test-image -m 1024 -hda ./UUID-disk.qcow2 diff --git a/f29-branch/_sources/composer.cli.rst.txt b/f29-branch/_sources/composer.cli.rst.txt new file mode 100644 index 00000000..81a5776f --- /dev/null +++ b/f29-branch/_sources/composer.cli.rst.txt @@ -0,0 +1,86 @@ +composer.cli package +==================== + +Submodules +---------- + +composer.cli.blueprints module +------------------------------ + +.. automodule:: composer.cli.blueprints + :members: + :undoc-members: + :show-inheritance: + +composer.cli.cmdline module +--------------------------- + +.. automodule:: composer.cli.cmdline + :members: + :undoc-members: + :show-inheritance: + +composer.cli.compose module +--------------------------- + +.. automodule:: composer.cli.compose + :members: + :undoc-members: + :show-inheritance: + +composer.cli.help module +------------------------ + +.. automodule:: composer.cli.help + :members: + :undoc-members: + :show-inheritance: + +composer.cli.modules module +--------------------------- + +.. automodule:: composer.cli.modules + :members: + :undoc-members: + :show-inheritance: + +composer.cli.projects module +---------------------------- + +.. automodule:: composer.cli.projects + :members: + :undoc-members: + :show-inheritance: + +composer.cli.sources module +--------------------------- + +.. automodule:: composer.cli.sources + :members: + :undoc-members: + :show-inheritance: + +composer.cli.status module +-------------------------- + +.. automodule:: composer.cli.status + :members: + :undoc-members: + :show-inheritance: + +composer.cli.utilities module +----------------------------- + +.. automodule:: composer.cli.utilities + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: composer.cli + :members: + :undoc-members: + :show-inheritance: diff --git a/f29-branch/_sources/composer.rst.txt b/f29-branch/_sources/composer.rst.txt new file mode 100644 index 00000000..5314fc0c --- /dev/null +++ b/f29-branch/_sources/composer.rst.txt @@ -0,0 +1,37 @@ +composer package +================ + +Subpackages +----------- + +.. toctree:: + + composer.cli + +Submodules +---------- + +composer.http\_client module +---------------------------- + +.. automodule:: composer.http_client + :members: + :undoc-members: + :show-inheritance: + +composer.unix\_socket module +---------------------------- + +.. automodule:: composer.unix_socket + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: composer + :members: + :undoc-members: + :show-inheritance: diff --git a/f29-branch/_sources/index.rst.txt b/f29-branch/_sources/index.rst.txt new file mode 100644 index 00000000..40acd5a6 --- /dev/null +++ b/f29-branch/_sources/index.rst.txt @@ -0,0 +1,34 @@ +.. Lorax documentation master file, created by + sphinx-quickstart on Wed Apr 8 13:46:00 2015. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Welcome to Lorax's documentation! +================================= + +Contents: + +.. toctree:: + :maxdepth: 1 + + intro + lorax + livemedia-creator + lorax-composer + composer-cli + product-images + modules + +Documentation for other Lorax Branches +====================================== + +* `Fedora 28 `_ +* `RHEL7 lorax-composer `_ + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/f29-branch/_sources/intro.rst.txt b/f29-branch/_sources/intro.rst.txt new file mode 100644 index 00000000..01857ee9 --- /dev/null +++ b/f29-branch/_sources/intro.rst.txt @@ -0,0 +1,67 @@ +Introduction to Lorax +===================== + +I am the Lorax. I speak for the trees [and images]. + +Lorax is used to build the Anaconda Installer boot.iso, it consists of a +library, pylorax, a set of templates, and the lorax script. Its operation +is driven by a customized set of Mako templates that lists the packages +to be installed, steps to execute to remove unneeded files, and creation +of the iso for all of the supported architectures. + + + + + + +Before Lorax +============ + +Tree building tools such as pungi and revisor rely on 'buildinstall' in +anaconda/scripts/ to produce the boot images and other such control files +in the final tree. The existing buildinstall scripts written in a mix of +bash and Python are unmaintainable. Lorax is an attempt to replace them +with something more flexible. + + +EXISTING WORKFLOW: + +pungi and other tools call scripts/buildinstall, which in turn call other +scripts to do the image building and data generation. Here's how it +currently looks: + + -> buildinstall + * process command line options + * write temporary yum.conf to point to correct repo + * find anaconda release RPM + * unpack RPM, pull in those versions of upd-instroot, mk-images, + maketreeinfo.py, makestamp.py, and buildinstall + + -> call upd-instroot + + -> call maketreeinfo.py + + -> call mk-images (which figures out which mk-images.ARCH to call) + + -> call makestamp.py + + * clean up + + +PROBLEMS: + +The existing workflow presents some problems with maintaining the scripts. +First, almost all knowledge of what goes in to the stage 1 and stage 2 +images lives in upd-instroot. The mk-images* scripts copy things from the +root created by upd-instroot in order to build the stage 1 image, though +it's not completely clear from reading the scripts. + + +NEW IDEAS: + +Create a new central driver with all information living in Python modules. +Configuration files will provide the knowledge previously contained in the +upd-instroot and mk-images* scripts. + + + diff --git a/f29-branch/_sources/livemedia-creator.rst.txt b/f29-branch/_sources/livemedia-creator.rst.txt new file mode 100644 index 00000000..4b4fea7f --- /dev/null +++ b/f29-branch/_sources/livemedia-creator.rst.txt @@ -0,0 +1,657 @@ +livemedia-creator +================= + +:Authors: + Brian C. Lane + +livemedia-creator uses `Anaconda `_, +`kickstart `_ and `Lorax +`_ to create bootable media that use the +same install path as a normal system installation. It can be used to make live +isos, bootable (partitioned) disk images, tarfiles, and filesystem images for +use with virtualization and container solutions like libvirt, docker, and +OpenStack. + +The general idea is to use qemu with kickstart and an Anaconda boot.iso to +install into a disk image and then use the disk image to create the bootable +media. + +livemedia-creator --help will describe all of the options available. At the +minimum you need: + +``--make-iso`` to create a final bootable .iso or one of the other ``--make-*`` options. + +``--iso`` to specify the Anaconda install media to use with qemu. + +``--ks`` to select the kickstart file describing what to install. + +To use livemedia-creator with virtualization you will need to have qemu installed. + +If you are going to be using Anaconda directly, with ``--no-virt`` mode, make sure +you have the anaconda-tui package installed. + +Conventions used in this document: + +``lmc`` is an abbreviation for livemedia-creator. + +``builder`` is the system where livemedia-creator is being run + +``image`` is the disk image being created by running livemedia-creator + + +livemedia-creator cmdline arguments +----------------------------------- + +.. argparse:: + :ref: pylorax.cmdline.lmc_parser + :prog: livemedia-creator + + +Quickstart +---------- + +Run this to create a bootable live iso:: + + sudo livemedia-creator --make-iso \ + --iso=/extra/iso/boot.iso --ks=./docs/fedora-livemedia.ks + +You can run it directly from the lorax git repo like this:: + + sudo PATH=./src/sbin/:$PATH PYTHONPATH=./src/ ./src/sbin/livemedia-creator \ + --make-iso --iso=/extra/iso/boot.iso \ + --ks=./docs/fedora-livemedia.ks --lorax-templates=./share/ + +You can observe the installation using vnc. The logs will show what port was +chosen, or you can use a specific port by passing it. eg. ``--vnc vnc:127.0.0.1:5`` + +This is usually a good idea when testing changes to the kickstart. lmc tries +to monitor the logs for fatal errors, but may not catch everything. + + +How ISO creation works +---------------------- + +There are 2 stages, the install stage which produces a disk or filesystem image +as its output, and the boot media creation which uses the image as its input. +Normally you would run both stages, but it is possible to stop after the +install stage, by using ``--image-only``, or to skip the install stage and use +a previously created disk image by passing ``--disk-image`` or ``--fs-image`` + +When creating an iso qemu boots using the passed Anaconda installer iso +and installs the system based on the kickstart. The ``%post`` section of the +kickstart is used to customize the installed system in the same way that +current spin-kickstarts do. + +livemedia-creator monitors the install process for problems by watching the +install logs. They are written to the current directory or to the base +directory specified by the --logfile command. You can also monitor the install +by using a vnc client. This is recommended when first modifying a kickstart, +since there are still places where Anaconda may get stuck without the log +monitor catching it. + +The output from this process is a partitioned disk image. kpartx can be used +to mount and examine it when there is a problem with the install. It can also +be booted using kvm. + +When creating an iso the disk image's / partition is copied into a formatted +filesystem image which is then used as the input to lorax for creation of the +final media. + +The final image is created by lorax, using the templates in /usr/share/lorax/live/ +or the live directory below the directory specified by ``--lorax-templates``. The +templates are written using the Mako template system with some extra commands +added by lorax. + +.. note:: + The output from --make-iso includes the artifacts used to create the boot.iso; + the kernel, initrd, the squashfs filesystem, etc. If you only want the + boot.iso you can pass ``--iso-only`` and the other files will be removed. You + can also name the iso by using ``--iso-name my-live.iso``. + + +Kickstarts +---------- + +The docs/ directory includes several example kickstarts, one to create a live +desktop iso using GNOME, and another to create a minimal disk image. When +creating your own kickstarts you should start with the minimal example, it +includes several needed packages that are not always included by dependencies. + +Or you can use existing spin kickstarts to create live media with a few +changes. Here are the steps I used to convert the Fedora XFCE spin. + +1. Flatten the xfce kickstart using ksflatten +2. Add zerombr so you don't get the disk init dialog +3. Add clearpart --all +4. Add swap partition +5. bootloader target +6. Add shutdown to the kickstart +7. Add network --bootproto=dhcp --activate to activate the network + This works for F16 builds but for F15 and before you need to pass + something on the cmdline that activate the network, like sshd: + + ``livemedia-creator --kernel-args="sshd"`` + +8. Add a root password:: + + rootpw rootme + network --bootproto=dhcp --activate + zerombr + clearpart --all + bootloader --location=mbr + part swap --size=512 + shutdown + +9. In the livesys script section of the %post remove the root password. This + really depends on how the spin wants to work. You could add the live user + that you create to the %wheel group so that sudo works if you wanted to. + + ``passwd -d root > /dev/null`` + +10. Remove /etc/fstab in %post, dracut handles mounting the rootfs + + ``cat /dev/null > /dev/fstab`` + + Do this only for live iso's, the filesystem will be mounted read only if + there is no /etc/fstab + +11. Don't delete initramfs files from /boot in %post +12. When creating live iso's you need to have, at least, these packages in the %package section:: + dracut-config-generic + dracut-live + -dracut-config-rescue + grub2-efi + memtest86+ + syslinux + +User created repositories +~~~~~~~~~~~~~~~~~~~~~~~~~ + +If you are using your own repositories and installing groups (eg. @core) make +sure you create the repodata with groups like this ``createrepo -g +/path/to/groups.xml /path/to/rpms`` + +Using a Proxy with repos +~~~~~~~~~~~~~~~~~~~~~~~~ + +One drawback to using qemu is that it pulls the packages from the repo each +time you run it. To speed things up you either need a local mirror of the +packages, or you can use a caching proxy. When using a proxy you pass it to +livemedia-creator like this: + + ``--proxy=http://proxy.yourdomain.com:3128`` + +You also need to use a specific mirror instead of mirrormanager so that the +packages will get cached, so your kickstart url would look like: + + ``url --url="http://dl.fedoraproject.org/pub/fedora/linux/development/rawhide/x86_64/os/"`` + +You can also add an update repo, but don't name it updates. Add --proxy to it +as well. You can use all of the `kickstart commands `_ in your kickstart. Make sure there +is only one ``url`` command, other repos have to use the ``repo`` command and cannot be +named ``updates`` which is reserved for Anaconda's use. eg.:: + + url --url=PRIMARY-REPO-URL --proxy=PROXY-URL + repo --name="repo1" --baseurl=FIRST-REPO-URL --proxy=PROXY-URL + repo --name="repo2" --baseurl=SECOND-REPO_URL --proxy=PROXY-URL + + +Anaconda image install (no-virt) +-------------------------------- + +You can create images without using qemu by passing ``--no-virt`` on the +cmdline. This will use Anaconda's directory install feature to handle the +install. There are a couple of things to keep in mind when doing this: + +1. It will be most reliable when building images for the same release that the + host is running. Because Anaconda has expectations about the system it is + running under you may encounter strange bugs if you try to build newer or + older releases. + +2. It may totally trash your host. So far I haven't had this happen, but the + possibility exists that a bug in Anaconda could result in it operating on + real devices. I recommend running it in a virt or on a system that you can + afford to lose all data from. + +The logs from anaconda will be placed in an ./anaconda/ directory in either +the current directory or in the directory used for --logfile + +Example cmdline: + +``sudo livemedia-creator --make-iso --no-virt --ks=./fedora-livemedia.ks`` + +.. note:: + Using no-virt to create a partitioned disk image (eg. --make-disk or + --make-vagrant) will only create disks usable on the host platform (BIOS + or UEFI). You can create BIOS partitioned disk images on UEFI by using + virt. + +.. note:: + As of version 30.7 SELinux can be set to Enforcing. The current state is + logged for debugging purposes and if there are SELinux denials they should + be reported as a bug. + +AMI Images +---------- + +Amazon EC2 images can be created by using the --make-ami switch and an appropriate +kickstart file. All of the work to customize the image is handled by the kickstart. +The example currently included was modified from the cloud-kickstarts version so +that it would work with livemedia-creator. + +Example cmdline: + +``sudo livemedia-creator --make-ami --iso=/path/to/boot.iso --ks=./docs/fedora-livemedia-ec2.ks`` + +This will produce an ami-root.img file in the working directory. + +At this time I have not tested the image with EC2. Feedback would be welcome. + + +Appliance Creation +------------------ + +livemedia-creator can now replace appliance-tools by using the --make-appliance +switch. This will create the partitioned disk image and an XML file that can be +used with virt-image to setup a virtual system. + +The XML is generated using the Mako template from +/usr/share/lorax/appliance/libvirt.xml You can use a different template by +passing ``--app-template