From b52e78c1ba7c902ea154625957414540ad25089f Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Thu, 1 Oct 2020 15:50:46 -0700 Subject: [PATCH] Add lorax 33.10 documentation in f33-branch --- f33-branch/.buildinfo | 4 + f33-branch/.doctrees/composer-cli.doctree | Bin 0 -> 71593 bytes f33-branch/.doctrees/composer.cli.doctree | Bin 0 -> 427259 bytes f33-branch/.doctrees/composer.doctree | Bin 0 -> 66251 bytes f33-branch/.doctrees/environment.pickle | Bin 0 -> 2519507 bytes f33-branch/.doctrees/index.doctree | Bin 0 -> 8778 bytes f33-branch/.doctrees/intro.doctree | Bin 0 -> 9140 bytes f33-branch/.doctrees/lifted.doctree | Bin 0 -> 125768 bytes .../.doctrees/livemedia-creator.doctree | Bin 0 -> 170060 bytes f33-branch/.doctrees/lorax-composer.doctree | Bin 0 -> 117777 bytes f33-branch/.doctrees/lorax.doctree | Bin 0 -> 81120 bytes f33-branch/.doctrees/mkksiso.doctree | Bin 0 -> 27673 bytes f33-branch/.doctrees/modules.doctree | Bin 0 -> 2568 bytes f33-branch/.doctrees/product-images.doctree | Bin 0 -> 7068 bytes f33-branch/.doctrees/pylorax.api.doctree | Bin 0 -> 1004255 bytes f33-branch/.doctrees/pylorax.doctree | Bin 0 -> 617363 bytes f33-branch/README | 5 + f33-branch/_modules/composer/cli.html | 259 + .../_modules/composer/cli/blueprints.html | 779 ++ f33-branch/_modules/composer/cli/cmdline.html | 251 + f33-branch/_modules/composer/cli/compose.html | 892 ++ f33-branch/_modules/composer/cli/modules.html | 249 + .../_modules/composer/cli/projects.html | 311 + .../_modules/composer/cli/providers.html | 523 + f33-branch/_modules/composer/cli/sources.html | 353 + f33-branch/_modules/composer/cli/status.html | 257 + f33-branch/_modules/composer/cli/upload.html | 478 + .../_modules/composer/cli/utilities.html | 324 + f33-branch/_modules/composer/http_client.html | 459 + f33-branch/_modules/composer/unix_socket.html | 262 + f33-branch/_modules/index.html | 250 + f33-branch/_modules/lifted/config.html | 234 + f33-branch/_modules/lifted/providers.html | 444 + f33-branch/_modules/lifted/queue.html | 468 + f33-branch/_modules/lifted/upload.html | 411 + f33-branch/_modules/pylorax.html | 657 + f33-branch/_modules/pylorax/api/bisect.html | 250 + .../_modules/pylorax/api/checkparams.html | 245 + f33-branch/_modules/pylorax/api/cmdline.html | 264 + f33-branch/_modules/pylorax/api/compose.html | 1468 +++ f33-branch/_modules/pylorax/api/config.html | 341 + .../_modules/pylorax/api/crossdomain.html | 264 + f33-branch/_modules/pylorax/api/dnfbase.html | 387 + .../_modules/pylorax/api/flask_blueprint.html | 255 + f33-branch/_modules/pylorax/api/gitrpm.html | 423 + f33-branch/_modules/pylorax/api/projects.html | 898 ++ f33-branch/_modules/pylorax/api/queue.html | 1064 ++ f33-branch/_modules/pylorax/api/recipes.html | 1477 +++ f33-branch/_modules/pylorax/api/server.html | 304 + .../_modules/pylorax/api/timestamp.html | 252 + f33-branch/_modules/pylorax/api/toml.html | 243 + f33-branch/_modules/pylorax/api/utils.html | 250 + f33-branch/_modules/pylorax/api/v0.html | 2198 ++++ f33-branch/_modules/pylorax/api/v1.html | 1243 ++ .../_modules/pylorax/api/workspace.html | 330 + f33-branch/_modules/pylorax/base.html | 268 + f33-branch/_modules/pylorax/buildstamp.html | 267 + f33-branch/_modules/pylorax/cmdline.html | 522 + f33-branch/_modules/pylorax/creator.html | 957 ++ f33-branch/_modules/pylorax/decorators.html | 231 + f33-branch/_modules/pylorax/discinfo.html | 246 + f33-branch/_modules/pylorax/dnfbase.html | 388 + f33-branch/_modules/pylorax/dnfhelper.html | 311 + f33-branch/_modules/pylorax/executils.html | 550 + f33-branch/_modules/pylorax/imgutils.html | 755 ++ f33-branch/_modules/pylorax/installer.html | 879 ++ f33-branch/_modules/pylorax/ltmpl.html | 1085 ++ f33-branch/_modules/pylorax/monitor.html | 404 + f33-branch/_modules/pylorax/mount.html | 305 + f33-branch/_modules/pylorax/sysutils.html | 361 + f33-branch/_modules/pylorax/treebuilder.html | 624 + f33-branch/_modules/pylorax/treeinfo.html | 264 + f33-branch/_sources/composer-cli.rst.txt | 203 + f33-branch/_sources/composer.cli.rst.txt | 101 + f33-branch/_sources/composer.rst.txt | 37 + f33-branch/_sources/index.rst.txt | 40 + f33-branch/_sources/intro.rst.txt | 67 + f33-branch/_sources/lifted.rst.txt | 46 + f33-branch/_sources/livemedia-creator.rst.txt | 670 + f33-branch/_sources/lorax-composer.rst.txt | 535 + f33-branch/_sources/lorax.rst.txt | 200 + f33-branch/_sources/mkksiso.rst.txt | 128 + f33-branch/_sources/modules.rst.txt | 9 + f33-branch/_sources/product-images.rst.txt | 27 + f33-branch/_sources/pylorax.api.rst.txt | 173 + f33-branch/_sources/pylorax.rst.txt | 165 + f33-branch/_static/ajax-loader.gif | Bin 0 -> 673 bytes f33-branch/_static/basic.css | 855 ++ f33-branch/_static/comment-bright.png | Bin 0 -> 756 bytes f33-branch/_static/comment-close.png | Bin 0 -> 829 bytes f33-branch/_static/comment.png | Bin 0 -> 641 bytes f33-branch/_static/css/badge_only.css | 1 + f33-branch/_static/css/theme.css | 6 + f33-branch/_static/doctools.js | 315 + f33-branch/_static/documentation_options.js | 12 + f33-branch/_static/down-pressed.png | Bin 0 -> 222 bytes f33-branch/_static/down.png | Bin 0 -> 202 bytes f33-branch/_static/file.png | Bin 0 -> 286 bytes f33-branch/_static/fonts/Inconsolata-Bold.ttf | Bin 0 -> 108360 bytes .../_static/fonts/Inconsolata-Regular.ttf | Bin 0 -> 95960 bytes f33-branch/_static/fonts/Lato-Bold.ttf | Bin 0 -> 657188 bytes f33-branch/_static/fonts/Lato-BoldItalic.ttf | Bin 0 -> 699008 bytes f33-branch/_static/fonts/Lato-Italic.ttf | Bin 0 -> 723544 bytes f33-branch/_static/fonts/Lato-Regular.ttf | Bin 0 -> 657212 bytes f33-branch/_static/fonts/Lato/lato-bold.eot | Bin 0 -> 256056 bytes f33-branch/_static/fonts/Lato/lato-bold.ttf | Bin 0 -> 657188 bytes f33-branch/_static/fonts/Lato/lato-bold.woff | Bin 0 -> 309728 bytes f33-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 f33-branch/_static/fonts/Lato/lato-italic.eot | Bin 0 -> 268604 bytes f33-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 f33-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 f33-branch/_static/jquery-3.2.1.js | 10253 +++++++++++++++ f33-branch/_static/jquery-3.4.1.js | 10598 +++++++++++++++ f33-branch/_static/jquery-3.5.1.js | 10872 ++++++++++++++++ f33-branch/_static/jquery.js | 2 + f33-branch/_static/js/modernizr.min.js | 4 + f33-branch/_static/js/theme.js | 3 + f33-branch/_static/language_data.js | 297 + f33-branch/_static/minus.png | Bin 0 -> 90 bytes f33-branch/_static/plus.png | Bin 0 -> 90 bytes f33-branch/_static/pygments.css | 69 + f33-branch/_static/searchtools.js | 514 + f33-branch/_static/underscore-1.3.1.js | 999 ++ f33-branch/_static/underscore.js | 31 + f33-branch/_static/up-pressed.png | Bin 0 -> 214 bytes f33-branch/_static/up.png | Bin 0 -> 203 bytes f33-branch/_static/websupport.js | 808 ++ f33-branch/composer-cli.html | 544 + f33-branch/composer.cli.html | 1501 +++ f33-branch/composer.html | 506 + f33-branch/genindex.html | 2040 +++ f33-branch/index.html | 245 + f33-branch/intro.html | 261 + f33-branch/lifted.html | 716 + f33-branch/livemedia-creator.html | 1102 ++ f33-branch/lorax-composer.html | 781 ++ f33-branch/lorax.html | 581 + f33-branch/mkksiso.html | 355 + f33-branch/modules.html | 309 + f33-branch/objects.inv | Bin 0 -> 4631 bytes f33-branch/product-images.html | 234 + f33-branch/py-modindex.html | 522 + f33-branch/pylorax.api.html | 5206 ++++++++ f33-branch/pylorax.html | 2246 ++++ f33-branch/search.html | 219 + f33-branch/searchindex.js | 1 + 170 files changed, 86523 insertions(+) create mode 100644 f33-branch/.buildinfo create mode 100644 f33-branch/.doctrees/composer-cli.doctree create mode 100644 f33-branch/.doctrees/composer.cli.doctree create mode 100644 f33-branch/.doctrees/composer.doctree create mode 100644 f33-branch/.doctrees/environment.pickle create mode 100644 f33-branch/.doctrees/index.doctree create mode 100644 f33-branch/.doctrees/intro.doctree create mode 100644 f33-branch/.doctrees/lifted.doctree create mode 100644 f33-branch/.doctrees/livemedia-creator.doctree create mode 100644 f33-branch/.doctrees/lorax-composer.doctree create mode 100644 f33-branch/.doctrees/lorax.doctree create mode 100644 f33-branch/.doctrees/mkksiso.doctree create mode 100644 f33-branch/.doctrees/modules.doctree create mode 100644 f33-branch/.doctrees/product-images.doctree create mode 100644 f33-branch/.doctrees/pylorax.api.doctree create mode 100644 f33-branch/.doctrees/pylorax.doctree create mode 100644 f33-branch/README create mode 100644 f33-branch/_modules/composer/cli.html create mode 100644 f33-branch/_modules/composer/cli/blueprints.html create mode 100644 f33-branch/_modules/composer/cli/cmdline.html create mode 100644 f33-branch/_modules/composer/cli/compose.html create mode 100644 f33-branch/_modules/composer/cli/modules.html create mode 100644 f33-branch/_modules/composer/cli/projects.html create mode 100644 f33-branch/_modules/composer/cli/providers.html create mode 100644 f33-branch/_modules/composer/cli/sources.html create mode 100644 f33-branch/_modules/composer/cli/status.html create mode 100644 f33-branch/_modules/composer/cli/upload.html create mode 100644 f33-branch/_modules/composer/cli/utilities.html create mode 100644 f33-branch/_modules/composer/http_client.html create mode 100644 f33-branch/_modules/composer/unix_socket.html create mode 100644 f33-branch/_modules/index.html create mode 100644 f33-branch/_modules/lifted/config.html create mode 100644 f33-branch/_modules/lifted/providers.html create mode 100644 f33-branch/_modules/lifted/queue.html create mode 100644 f33-branch/_modules/lifted/upload.html create mode 100644 f33-branch/_modules/pylorax.html create mode 100644 f33-branch/_modules/pylorax/api/bisect.html create mode 100644 f33-branch/_modules/pylorax/api/checkparams.html create mode 100644 f33-branch/_modules/pylorax/api/cmdline.html create mode 100644 f33-branch/_modules/pylorax/api/compose.html create mode 100644 f33-branch/_modules/pylorax/api/config.html create mode 100644 f33-branch/_modules/pylorax/api/crossdomain.html create mode 100644 f33-branch/_modules/pylorax/api/dnfbase.html create mode 100644 f33-branch/_modules/pylorax/api/flask_blueprint.html create mode 100644 f33-branch/_modules/pylorax/api/gitrpm.html create mode 100644 f33-branch/_modules/pylorax/api/projects.html create mode 100644 f33-branch/_modules/pylorax/api/queue.html create mode 100644 f33-branch/_modules/pylorax/api/recipes.html create mode 100644 f33-branch/_modules/pylorax/api/server.html create mode 100644 f33-branch/_modules/pylorax/api/timestamp.html create mode 100644 f33-branch/_modules/pylorax/api/toml.html create mode 100644 f33-branch/_modules/pylorax/api/utils.html create mode 100644 f33-branch/_modules/pylorax/api/v0.html create mode 100644 f33-branch/_modules/pylorax/api/v1.html create mode 100644 f33-branch/_modules/pylorax/api/workspace.html create mode 100644 f33-branch/_modules/pylorax/base.html create mode 100644 f33-branch/_modules/pylorax/buildstamp.html create mode 100644 f33-branch/_modules/pylorax/cmdline.html create mode 100644 f33-branch/_modules/pylorax/creator.html create mode 100644 f33-branch/_modules/pylorax/decorators.html create mode 100644 f33-branch/_modules/pylorax/discinfo.html create mode 100644 f33-branch/_modules/pylorax/dnfbase.html create mode 100644 f33-branch/_modules/pylorax/dnfhelper.html create mode 100644 f33-branch/_modules/pylorax/executils.html create mode 100644 f33-branch/_modules/pylorax/imgutils.html create mode 100644 f33-branch/_modules/pylorax/installer.html create mode 100644 f33-branch/_modules/pylorax/ltmpl.html create mode 100644 f33-branch/_modules/pylorax/monitor.html create mode 100644 f33-branch/_modules/pylorax/mount.html create mode 100644 f33-branch/_modules/pylorax/sysutils.html create mode 100644 f33-branch/_modules/pylorax/treebuilder.html create mode 100644 f33-branch/_modules/pylorax/treeinfo.html create mode 100644 f33-branch/_sources/composer-cli.rst.txt create mode 100644 f33-branch/_sources/composer.cli.rst.txt create mode 100644 f33-branch/_sources/composer.rst.txt create mode 100644 f33-branch/_sources/index.rst.txt create mode 100644 f33-branch/_sources/intro.rst.txt create mode 100644 f33-branch/_sources/lifted.rst.txt create mode 100644 f33-branch/_sources/livemedia-creator.rst.txt create mode 100644 f33-branch/_sources/lorax-composer.rst.txt create mode 100644 f33-branch/_sources/lorax.rst.txt create mode 100644 f33-branch/_sources/mkksiso.rst.txt create mode 100644 f33-branch/_sources/modules.rst.txt create mode 100644 f33-branch/_sources/product-images.rst.txt create mode 100644 f33-branch/_sources/pylorax.api.rst.txt create mode 100644 f33-branch/_sources/pylorax.rst.txt create mode 100644 f33-branch/_static/ajax-loader.gif create mode 100644 f33-branch/_static/basic.css create mode 100644 f33-branch/_static/comment-bright.png create mode 100644 f33-branch/_static/comment-close.png create mode 100644 f33-branch/_static/comment.png create mode 100644 f33-branch/_static/css/badge_only.css create mode 100644 f33-branch/_static/css/theme.css create mode 100644 f33-branch/_static/doctools.js create mode 100644 f33-branch/_static/documentation_options.js create mode 100644 f33-branch/_static/down-pressed.png create mode 100644 f33-branch/_static/down.png create mode 100644 f33-branch/_static/file.png create mode 100644 f33-branch/_static/fonts/Inconsolata-Bold.ttf create mode 100644 f33-branch/_static/fonts/Inconsolata-Regular.ttf create mode 100644 f33-branch/_static/fonts/Lato-Bold.ttf create mode 100644 f33-branch/_static/fonts/Lato-BoldItalic.ttf create mode 100644 f33-branch/_static/fonts/Lato-Italic.ttf create mode 100644 f33-branch/_static/fonts/Lato-Regular.ttf create mode 100644 f33-branch/_static/fonts/Lato/lato-bold.eot create mode 100644 f33-branch/_static/fonts/Lato/lato-bold.ttf create mode 100644 f33-branch/_static/fonts/Lato/lato-bold.woff create mode 100644 f33-branch/_static/fonts/Lato/lato-bold.woff2 create mode 100644 f33-branch/_static/fonts/Lato/lato-bolditalic.eot create mode 100644 f33-branch/_static/fonts/Lato/lato-bolditalic.ttf create mode 100644 f33-branch/_static/fonts/Lato/lato-bolditalic.woff create mode 100644 f33-branch/_static/fonts/Lato/lato-bolditalic.woff2 create mode 100644 f33-branch/_static/fonts/Lato/lato-italic.eot create mode 100644 f33-branch/_static/fonts/Lato/lato-italic.ttf create mode 100644 f33-branch/_static/fonts/Lato/lato-italic.woff create mode 100644 f33-branch/_static/fonts/Lato/lato-italic.woff2 create mode 100644 f33-branch/_static/fonts/Lato/lato-regular.eot create mode 100644 f33-branch/_static/fonts/Lato/lato-regular.ttf create mode 100644 f33-branch/_static/fonts/Lato/lato-regular.woff create mode 100644 f33-branch/_static/fonts/Lato/lato-regular.woff2 create mode 100644 f33-branch/_static/fonts/RobotoSlab-Bold.ttf create mode 100644 f33-branch/_static/fonts/RobotoSlab-Regular.ttf create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff create mode 100644 f33-branch/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 create mode 100644 f33-branch/_static/fonts/fontawesome-webfont.eot create mode 100644 f33-branch/_static/fonts/fontawesome-webfont.svg create mode 100644 f33-branch/_static/fonts/fontawesome-webfont.ttf create mode 100644 f33-branch/_static/fonts/fontawesome-webfont.woff create mode 100644 f33-branch/_static/fonts/fontawesome-webfont.woff2 create mode 100644 f33-branch/_static/jquery-3.2.1.js create mode 100644 f33-branch/_static/jquery-3.4.1.js create mode 100644 f33-branch/_static/jquery-3.5.1.js create mode 100644 f33-branch/_static/jquery.js create mode 100644 f33-branch/_static/js/modernizr.min.js create mode 100644 f33-branch/_static/js/theme.js create mode 100644 f33-branch/_static/language_data.js create mode 100644 f33-branch/_static/minus.png create mode 100644 f33-branch/_static/plus.png create mode 100644 f33-branch/_static/pygments.css create mode 100644 f33-branch/_static/searchtools.js create mode 100644 f33-branch/_static/underscore-1.3.1.js create mode 100644 f33-branch/_static/underscore.js create mode 100644 f33-branch/_static/up-pressed.png create mode 100644 f33-branch/_static/up.png create mode 100644 f33-branch/_static/websupport.js create mode 100644 f33-branch/composer-cli.html create mode 100644 f33-branch/composer.cli.html create mode 100644 f33-branch/composer.html create mode 100644 f33-branch/genindex.html create mode 100644 f33-branch/index.html create mode 100644 f33-branch/intro.html create mode 100644 f33-branch/lifted.html create mode 100644 f33-branch/livemedia-creator.html create mode 100644 f33-branch/lorax-composer.html create mode 100644 f33-branch/lorax.html create mode 100644 f33-branch/mkksiso.html create mode 100644 f33-branch/modules.html create mode 100644 f33-branch/objects.inv create mode 100644 f33-branch/product-images.html create mode 100644 f33-branch/py-modindex.html create mode 100644 f33-branch/pylorax.api.html create mode 100644 f33-branch/pylorax.html create mode 100644 f33-branch/search.html create mode 100644 f33-branch/searchindex.js diff --git a/f33-branch/.buildinfo b/f33-branch/.buildinfo new file mode 100644 index 00000000..f79cfffa --- /dev/null +++ b/f33-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: 9b3b905a33a257ccd41a2e1f4238d37b +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/f33-branch/.doctrees/composer-cli.doctree b/f33-branch/.doctrees/composer-cli.doctree new file mode 100644 index 0000000000000000000000000000000000000000..d22943c021532a46cd106743855cc56a6ec659a6 GIT binary patch literal 71593 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 aa>4K7Pt-G~zUJ{Y;Xg&6giE}e?f(Orrm1NF literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/composer.cli.doctree b/f33-branch/.doctrees/composer.cli.doctree new file mode 100644 index 0000000000000000000000000000000000000000..174b6a9ac8f7529dd4928daaa777f407ecdc6d07 GIT binary patch literal 427259 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�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 M$g=f_&X3vu2OJ2a%K!iX literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/environment.pickle b/f33-branch/.doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..2cbef6331b31f270d9814541181ea2cd10942f34 GIT binary patch literal 2519507 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 z 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

qapp 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ɂ*?xp3$PeVupBF}8f&l)>#+%&u?^d?6T7e%`*0A4a0Ewj0w-|>XK@}E za2Z!{9XD_bw{Z{m@d%Ic6wmMyukaS{@DZQz72og^zYu6+0D%ztkQez-5QR__#ZVHZP!{D-5tUFC)ld_) zP#5*k5RK3j&Cn99&=&2`5uMN#-Ov-g&=>tM5Q8uj!!Qz~Fc#x55tA?#(=ZdWFcV8(Km2h zK*a|XRD3`|Wj!7sv{lgY;dj63fjPi&=xj<_OK~*gw3H7Yz19lYv>ByV0-8e0q6m}pf~h| zeh`Fg$brEy1cpK`41?h?0!G3p7z^WI0!)MgD1_ai2&Td`m;rmjOqc~BD2FgqK?G() z9YkRth(ikI!hBc&i(o%E01kvh;7~XmmcmhRG#m%V!-;SboC>GGnQ#`I3+KUwa1mSz zm%){A6IQK?m3ZwuFB|XV?b1!gjDd z>;M7i3B8~X^o0Qsgh7x4JHZh6H{?Pd42O|03dX`Xm;e)@019DuD1xal4fcQ;uoujP zy&(jZ5QZ9vKrPfkJ?sMsNJ0b5gN3j!EQbBzAUGJ7z+rF%90|w3v2X$`gOlMDI33P_ zv*8>#A1;84;S#tUu7IoI8n_;AfSchKxE=0*yWt+VA0B{*;SqQoo`9#}8F(IEfS2JF zcpct=x8WUlA3lKP@G*P_pTi3H3ciK!;79lgR>H5a3O2Z2Xbo*(V`vNQpgnYej<6+k zg3izdx1R)!8U@#1Uq400Wg*+GzBViPbg>f(eCPD!e!tPK6 zQ(+p+fIVR*%z_YYyI>fh44$0p`I%*cTSV{%{Z+42QxJI2@M3k#H0o z1INPgZ~~kNC&4LjDx3~yz*%rMoD1i{g>VsE3YWo^a1~q&*TIc&6Wj{7!JTjy+za=? zgYXbM3Xj2)@Dw}?&%ulE61)np!JF_FybJHa2k;?$44=T~@CAGYU&D9sJ^Tbe!>{lg zY;c3n3O0m|U=#QUYzmvf=CB291^d;*`s7w{!~ z4d1}`@B{n|zrb(sJG8n{Xbl^|#_$hl2b)0$*aEhMe?n*22D-v_us!Sm0q6<6pbzwg z0T6^ikOMox5coIbLLLlCKkb=1|9~QtO*bfeX1K|)j6b^@_a1@HjjHPs20tJiGue!z=JQya8{+JMcby z0L$TH_zXUW74Q{&3*W(y@Dr?rUttw&aFfsmHiWjY3ABezp(AV#onR~I0$W2j*cQ5j z1wG(j&>OO#AM}T87zl%5M;Hn_!!XzdM!>Ex8pgnQ*bVYw5=@3EPz)t79rl1y*bB;F zZ>WGusD>Jt1GNx?dPqPL8ekqQgneN#><72+47b4Ta0lEC_rU$|06Ywjz~k@)JPpsl^Y8+^46nfJ z@CLjM@4)-;0W61);WPLgzJwL<4SWkfz>n|?tc2fT6|}xtXagHVTWAOEp#yY;Euj;1 zhAyxTbcO9;d)NU2&=Yz=ALt7MAP9pX2X=xX@NdY4JQxlmVHAvoaWDZULID)Q?ob3% zVH(VUJz*xyf)JEL7^)xwv!M>6un)u`1#@9OEPzF@9~=M&!Xa=d91ct2C^#C9gX3Wt zoCv4Dsc;6I3FpAMZ~TWw1N#`BiID~ z0h_{R&=EF=POuepfvuq%Yzy7Nf&lb@UeFu*LO%#XHsruy7y?5f7ly%b7y+YTG>n7s zFcI>h5GF$r6vH%_4tqi=%z`o~hYF~IYM2dkAPO;vLjvYP11x}rupcaj1K}Vz6qdkJ zI0BA_W8io=0ZxLG;WRiM&VsYyJUAaNf{WoYxE!v6tKmAh9&Uo0;WoG(?t;7FKDZwq zf`{QTcpRRBr{Otx9$tc%;Wc<2-h#K`J$N5Jg5~fjdMIF3H}M4VH@ZQ+rjp*0|cNa^nyOn7Y0BO20;$&1ViB8kPCS* z97e(@7z^WI0!)MgD1<4nJCwjw*aK$3UN95(h7eRj7-}E_wNMB3un#051@mA&>eaRhC|>mI2?|Iqu^LL4wk`*a0;9XXTX_o4x9@Yz=d!LTnbmfm2eGQ3pc=xa0}cD zcfg%+58Mk6z=QAzJPJ?1lkf~Y3opQn@Cv*NZ@`=I4!jE=z=!ZLd;*`t7w{E)4d21{ z@DuzDzrt^@!EHh-*bp{?P2eA}DQpIt!xpd={1di@ZD3p24lLLK{slduH)KIS=nvU2 z5C+4JFcfx%VXzB~fL&oUjDhj68|1?zm<&^(7)oF|>;a{)7nH%?Pyv-t4K*+aY9R*o zkbopKz&uz8`@&+_9}a?pVF?@tOW_DO3XX)VAkuraiScF-O=Ku6dTIzeaX0$rgS zY!BTb06m}=^oG9B4}y>lIWQQ8z);AAVK5vQ*2+W2$h(bN=0|`h%1I&YkurDlz{ox=u7?!|ca0DC)$H1|00xW}*;S@L> z&VaMw95^2?fQ#W0xE!v4tKk~B9&Uh};TE_Z?tr`D9=IPKfQR7`cpRR9r{NiR9$tW# z;T3ot-hj8^9e5u;faUNpdPg4TBkZD3<)3+;yyL-;fJ=FdRn0C>RUlU;<2p0w{#t zp$MkJG?)QVsE3YWo^a1~q&*TIc&6Wj{7!JTjy+za=?gYXbM3Xj2) z@Dw}?&%ulE61)np!JF_FybJHahwu@60-wSc@Fjc=-@y0q1N;oXz;Ez7w7OGh4I9D6 z@DFGQn?VQI0=9&ILTA_py25s_J?sDh_!snqEa(IMVE_z-L9iq21UtjOVHe1QU121Q zfw8a~On^yH08?OhD1oW42h4!IU?%JhA*h5f)IbDkp$_U{A4oz9=D~c}7Z$<(Z~z<( zhrnTQI2;K_!Le{0EQ1r_6gU;mfHUD7I2SH}3*i#D6s~|P;TpIWZh#x%7PuAefIHzH zxECIP2jLNT6rO-5;Td=qUVsO`#)f4xL~t=mJ|qH`o@sg9Sa{U(g$}pda*yY#0cGVMiDW zJHs&81xCQGFdD|dc-Rf{VG>M+DNqb0Fdg=QQrHX1U~i~^N~ne!m;<#CgL+6n5*lD0 zEQEbwG3*Zq!NITu4ud1$NH_+Lg%e;IoD8SH>2L;|4d=l5Z~+lA=4e!AF@Bu7`kKr@;99F2z;xIHN?|W3gT0{wDxn%`U=Gwm z4C)~PNoat1un_iz#jrmd1P8+sI1G+}BjFf07EXX=a59_%r^6X=Hkv3N1J}b1a5LNjx5FK9H{1jF!vpXzJOYoy6Yw-V1JAGx!o#z&G$M`~W|~FR&7RhgHz}9-$3v3~iwuw1*DR5w?U*&>6ZwSLg=YLw5*3 z59kHGp)d4l90j<7j&f~}wn zYz^IDTj&lJ^niasZ^(jv&>ym4APj~bVJPej!(bN}0lUIz7z5*BH<$?dPymInI}||) zOoi#N2b98IPzHNL1yn*c)W965g&5RB0+P@G^I#$D3yWcYI0z1gC2$xV0Y}0ya4ehv z%iv@<1x|-E;A}Vt&W8)&Vz>k@hb!P}xCX9+>)|H28E%8y;V!rv?uGl{L3jurg~#AY zcnY3{=io(n30{F$;dOWe-h#K`J$N5Jg5~fjdMIF2|7a;=nCCnd*}`U=mEW;H}r*m5QJ>Vfx)m741s?`F66;*7zv|b zER2H*FcAu%5O#+mmVU63Rl3Da1C4wH^7Z>3)~8Kz@2ap z+zSuDgYXDE3Qxe3@C-Z)FTjiN3cLz$z?<+6ybB+|hww3c0-wVd@D+Rw-@*6r6Z{On z!f&v_{X#3)5H^BM;2*FlYzCXd7O)lk6Sfvov$qj>b+;Rfwu9}#f*qg-{0n+PZ|DPk zp+5|OY#0bRFc@}%A+R(28-~FyFdRm}NEiiUU@VM>-C!c*Lje@R6xbb#p#-MEbeI8q z!d@^F%3yCOhYAQo71Tfk=0Gh(AqM+E9FmZN2ABs6U?D7m{a}AM01kqK;ZRrthr?1h z5{`mn;8-{wPJk2PBsc|5h11~-I1A2(bKyL=04{`!;S#tEE{7}OD!2x&h3nx4xCw5C zTj4gi1MY;o;U2gT?uQ5AA$SBHg~#CucnY3|XW=<`0bYcc;T3odUWYf~EqDjsh46bGHqaHeh3%j_SP+07&=Yz=7W9FB&>w=34TB&Dc7&Z^DC`WmFbwiwIP3}| zVKj_^aWEbxz(kk?1uz+=KoJzfRG0>Pzzisby)-~s5pITC;5N7&?u5JG9=I3ohX>#xco-gq z$KVNg5}t-<;5m36UWAw66?he1hd1CYcpKh@_uvB|HTy%6%eS0GpTMW^IeY;t;4AnB zzJ>4M2lxqohL!Lu{0^(2)q_H7*bp{?wy+7bgZ8i)bb!ra3+Mz}L1*X!+dx;?7Pf=# zU_k(SKu_oeS*a2y;D%iu&f8BT%I;B+_>&VqB`TsR*tfQ#T_xD+mfE8t4F z8m@us;Ci?bZh~9jR=6GRfV<#sxEJn&2jD??7#@Mg;Bj~oo`PrKS$G~^fS2H9coklQ zH{eZp8{UEU;C=WIK7x^4O!3^`oRDQ!ax`VgJDM) z0z={7kPEv&9*lrpVHAvpu`mvHg9(rilb{eL!|qT7B`_7H!yd3Fl)_Ay1$#pXDxeao zpc*1D8)~5rVo(opNI(ka!aSG{3t?Z_4;I4#a3CBEhrkjz43@$Xa18~Wd;wp= zSMW7_3*W&H@FV;Tzre5X8?1s29u`_d8`uaohE0Uj?0<+9lI>a40Xo8#&=!0~VboCGJsX>dB6 z1!u!~a6ViF7sF+6Ia~!-!*y^y+ypnnZE!o>1$V=Ja6dc*55r^dI6MVU!*lRFyaX@9 zYw$X}1#iQ9@IHJ5%i&Y_48DXF@C|$mKfsUh3#^3SVHLD~L}&vWLtAJE?V$s7ge{>H zbcQa_6}rLp&>aHM1A0Mk=nMTI2-%PWgJB2^gg5J;<`auw~AqNJ-5Eu%%Fbsyn2p9#UVH}KyiI5M4 zFd2%V7^cB=*b_=&7L-9bR6rF}!)%xXQHVht5-=AUU;!+I{a`U12nWHTumqOE5pXmd z1INP&a1xvhr@`rP7Mu;|!TE3zTnv}Nz@DjWXufgl^7Q7Ab!TazLEQe3wGx!o#z&G$M`~W|~FR&7RhgHz}F`*4? z3~iwuw1*DR5w?U*&>6ZwSLg=YLw5*359kHGp)d4DR>&5gXiHTco|-U*WoRA8{UKW;UicMpTcMGC9HsN;9K|seuQ6OCHxMn zp!MTI8`v1yLOW;=9iSs@37w!bbb+qW4Yr5w5P%-g3wlFe=m$Z_h8!3SLtrT6!Y~*P zBVZJahH)?+CPF?G!el6dVweWgVNWQ9Sx^S$Pytm?4YOemL?H%oNWffZfCaD+_JhT6 zARGjT!V*{tN5Ii=3>*(9z)5g2oCc@ES#UO-2j{~@a4}p4m%~+XHCzYR!%c8A+y=M9 zU2r$t2lvB6@Gv|EkHb^&G&~2-!%OfoyaunsTktl#2k*m2upB;x&)`c~0pGy4@B{n^ zzrafP9acf>CxkYzF|>tt&>lKKN7xcNL1*X!U7;In58WXEJ)jr#hQ81bf{+b4Fc^lw zP{@U0FdRm}C>RanU_4BOd?Pg4Rz8ZD3<)3+pMb04Kr8a2lKrXTjNU9-I#s!NqVHTn<;k z)o>kL4>!Tha2wnXcfs9oAKVWQ!Nc$vJPuF6)9@TT4==&X@EW`hZ^7H}9=s19!E*Q% zK7%h|1$+bF!VmBx`~oZCcUT3jpAy=@#?ThpL3`)`9brr81f8J^bcJrPJ#>cv^nhN_ z8~Q>&2tqdGz+e~xLm?N2!EhJ>qhK_QgYhsC@}UqWLlG3iG?)&1LMhCGGAM@%sDf&k z4Rat0F^EF~=0XE3fQ7IhEQSN&AUG73z)~SK`v{SStfN?T3>*u`!wGOAoCK%9sc<@+ z0cXM4a4wt&7r=#ZF!RzoQyan&TyYN1I03X3}_yj(M&*2ML0bjv4@GX1~ zKfq7$GpvMP;dfXCt)3QI!-lXCw1rKe9khqdpaX0UTR+fwrJUrTa?X>gc~YimEp3w zSY@gmSyd+a)%8z=+Ul+H9A&5KOU*BNm^N> z`&c;x2kmTGMd3ACFbXLv@z?Srre5twgLU*$|3{hgtJu zDXStBwc_E*NFo`Jl&6wmE0VNA(aP*t+>-D_s^-gXWKk+w8ID`Yny@8jQX@&Zb6oDCgG@sjaoj!&WL0u1eMRmm|r=u%=Ha*=_RF5^H4P3~TzxqN0(7B{PP} zy2+ZD{2G?qsP+`8tC#yzX~|WMhoZ^(5_H)?!PuhFyU7+KM@^VCp=5@H-x@ceq;PC; zu{CaTku}nqGP0;-!sw}!MiyC9rWQ?^Ts$^tS;caFdl>?}_Z;ghnn&ES|J#W7XA>XmvaJUn|f4SFk#q zoFqSl<5>Yanh%f|9_Z7~-Y%A~|4Phv{+ykNMcY-yV|7+4URxU}57vj`64A_|WSRPR ze|}9x)!*&(>h?i`sc2+gSt3?3CoDHzhj6Ma+O4Ey%IH`$8m=HtO^L;7+qJ6Sz{$*Dr$_JGQo;VWC^!Zo8(Hc zBq@4!m@A1iY{y;u7O@pO2-VJ!{|#E<>Yx=E7|^>&&X;)W+k>QC@7^WIdausGJv;O4 zL#^j*8&{{2&|69xsO37cp(F{52uJc&r$YW)l$hgxsxU zO)wgZ*YQVIAX`o$dv4D}cF#n>>M04k@kN%{pl?EbI9ge@PbwUrpCv)+Z>c}sdoZ$+ z7_Jstp?GzwPI5}Z9kQktP12X0ORQHg=|fVw$-(5z>a2jeEraqJBsb`#{?5sh)Ey7> zw<5uCu)oB7buzW#P^Cm?tM`cBL3Q7v;Rdr~$;LuXE)uFI%n}s{hGbCTd6K`94v01; zAd=rktAoC1;oP{GWbKitP2m2xg+BwA6Ml9SQ<%W#|34-&RA2~jd3>0JJnKNDeYS0D9jq>6=lg`f_NTF$x2 z@%7!+TY6Wr`dNWq0a0zDwg}fI!aDgi-qu~m#5p;l$p^AZouiiyoT<{VK1}H#-@kHZ z_IHBC?mhpxI~XjRIAQkgYp0nrO`Mesj*O!$9%{(a*^L}7S<`gpAuCFDok-Qn^^=Gh zvc``skp*%}iKH)zc=ncSO_6=7q%F~#d`yaVm9=>iEy+}}zdFhJDpWzM&QC`t-@cr< zp`(?AK3ByG*_Ry-u12Pa=!;F}OzLCQ0aRv9z9AJENlyCM8DbE7rbv+(kU2m0UPT?F z;<7HA1Wo9&0&>YDy-L8HC>IYVlA&ZuqGX=6&ZnInYP%h`>qw4d{IZs6MbgnV|e{sl9wAM;RCLMNc-ZOH`94O2efA`7kD8VzJ1rnzZ14j*|jj3W0=_@=_tD$d6T3CBjLm z*2!_5ay21`qgqIoLIR-LtS(wrI9X96wZ~c~-q=-!YN>*93shd_FYkOA&|fh#`vb9u zs*C)8NV4=Y`wnH1$(TDt*5I!|sp^BBymTGcBZK}^pa$L#Z zbe+RnO$(TvNwr>uSYL)FvTbKqdSx!Wv%WXQ=!L%A+LLZLP7iCkJV(kyRLlvzzOocX zDkPGb%ae?gZrox)2cjw}VQhTs^tJ6_QQ4$GGuPbQ2dU|m%VQ`>MJ}E^`LYW2Dz!)* z)Jefq44S)MJu9gW+d;{4uY@U%;%;Wp#I^Jt%3OS%8ThWGvszPEQ%B+2a5AhaGi;oe z{kZu}vDA2_;xcCJq_HJq?exxF;979b@;ZEv`{%Wf^Tnssz z|4O-{gX*p8tgdKrD>UknN*b0_{WR@v_P5GomGj+uDs2){4VAj7db%<9(s`;f53~P` zTwL8U6}o0_n6AlkM*8_korGO1vDkhFWJfBI>f5fja4N+5;+hBJ|K@!snEI|a@svWq z^B@?GW~j)nWh{{_x30EjQ6*%ROfHy28vswq>*GsUJ!Aa0@`<&NFHOX+8fpHJ=GnZ3 z0ckBuN;AuV5^3`ZZ<11*I$dk%47Bd+$rbMhRY^kDTefIRX z&Yspdx=CeInwwR7MmF(fE#n-`G*yw>Fx@g)CUU!l-*{8^wbyW4Gn{f?Z{w@L*uUu_ zN9sM&P(9eq0d)1*Q`orc7n$0G{!z66$X)fe0niK~4`b40L;bZXqAFZY@a%34l}OD_ z>^9wT<}CF&RG8E&ogz{dh|uV5nNy(#o!dkUjWps*3rTsZIxDc7&IzOfDy_Hu&Bh6x z@M$Z_aD;%WbW0%3g?6jmnHoC^W75T?^O!Mdp&Vvk0v=E7^QZTK&?n>b-CfV=ZGz@uD8qF!AvK2!&#MU6Cw;NNJ(fC-I%%`oShY5{Q=UOQ&7_$E zq*|4vuR^-pq^!2Xwz>$C%MF+36S+cJ;YN*6b{l_rNUCQfskx>pqcYYIrJYSBwhT21 z)k7IhB=Sn)DNhT=7_*r?RS-PsdJ4@Ytdayw)nfGYF>bT9-A?VCi!WXNRcopCL;V^& zwyP-C)UzKQB=zyIy4)sq<*8OlCvmRRR#7q{Un{5^I|=50w(--6w0S)0yIHw(n(Nf= zoU4wf4Y3NGKiPYB<-|Xm1ytlVhsg5%wQ&erZG|TGa zu{cADQ@^Y2=s=bZ>~Pcxh_vlCln10YTl(nTE7(vY(cU6axXakNs_x`jacTPwRb~wu zX!W%Q4b0iGZ{Hj@0IX*kI#}Jm1AZ)*jpsP0!IG+ALtNSzbt{!lJS^rv*^`|})Az*w z%h*(^gmMk5g2`}gZI(YMW+%Q?hg&=jqNhxUExuP%-gnr!F7qzA{}lf=I4|C&4MoKY<~qNnR1!%nMeQ;8b6KI(z3YmUTK-N=Q9z zL*~Z=@{f`qH?i9o%+h1>&yuB^*-O;4?{(bV33Z{L7%|;L8zs5#( z(o|{R{Pae_hOL$?OEHSZxl*&wYrVk+jW3Z}mVOp$apOJf?Y+6oGP6(bl`_kkyn1Rc z{@bAzd9Ic|x^tcM#b~sU$1HuQR1*V*lFK|lNZ+45>On>jo%oOSBZ$_IAfg$pF7`JV zL8SV4_3$@mNRaB~w*O@wvD&qh(Mu&YVd=Tbu_|gq2^orHHP8_dstnaj&zWj}PN<<; zRSeeR3eeA`3S-sTVfG}$m#oQV07mV6T_GkE2^sKIEhTrVJSg2?*>#Cfxs2tBWt*<8 z!~oKnu4ZPJ*T%}T>p}?`m*)H~*{Jio4pUqP#mqP1mhjZp#u}(^G)OJL4z%h)R}CFB z=;^>za{loFvS|<11>PuN`sZwCEni^Fk4YJ)CeMEHWHy1Ks39ckvSsLj&+^=apntHG z49im;LQ<1br5Sw&WirAsk}NCBN`z~xq#mViml*&-f3}q7c|!*F-N{q?l3MU+sgKC; zLm7_95qL5(qQ=@WFWPw(1TMX0t$TH||5 zzpA-1=6~J#3L6DI7g4HMo_{$Za8{Gw=?V7U4=Jh5?dX$B4;fErI+4gFm2^TaUJV(n z>@DL`on1<;&)KWLe&#F=R@BNURlA|sZh zVDaS9`DMi=MPo-6crJtNASgZ3=K84p2h%SWYk7mgzN+1Jzrsa=zCpV5GfW1<gsO?(EDtx(ykpb zq{_^YEhoyVe|gdrBfvO|#_`-#)zeeIj+)%g>hewoKpOvLiQAB?3y2{{?vXKgc%o9C*$2rj|Su4eE+PG zaVE9lGTKO_Z$*Y*wd4r(p^7=7>Tu!MX+P@2sX5}2?m{@iie z(?XK%Pz^Q3i+(JS#xZHEOq!-PyW2*ZlXM`|+duU2gk)@g@-0 zV7ttfGcT(PF)VkXTOP|RJxS^FRsXrWD`To^KQE9meRodgjYEm-T zS+ZVflwmloUdeN4&)&M)azS%7g_O&{&aOE%OpkhkzJ*gn_2oOo>;24lyqxv z=O$86b#DG88?iKZ=dY%)Ujo7(FJ*n4b5d%FfWowl=M50wOd6RO4 zj*)q4Af9wrJBM=%L!GEhu488$(leNzM09S!J9wOmWIgI^oKn1TIy05F^!>Cnsd;aL z*_nP>DkQI#m;%N*A%8`Cec2}kr=6?*rOH10MrKNQ&E9b5PV2J3E;>~cvwmvO?}Esi zPtCtqQx}>SsY}&)-mH<{)kK7n+yst&tGG>e(8C%_d~*)3W=K$t;~{Cutg4bOCG~!> zymX~n5$*TCYb6=W+nN+(&b~}qkq~5+RygnJs7PHw2EcF#e{seeq=aIvG68cs_8ZlK z{-)gY<}-cl*GSZ}@mf|Pc<44Sota}g_u|i}U8H5CnJNZu-K5cDNojz=X;O1=ZWH^{ z=fO>J?!1f@G>@k<-JNlBWPDXJIe)Y~@kf$l^b8DHdR2cOX;(&?UZ1K2b)dW*y^Ra< z1n)12dQ01i3W_QDyE&t$>U>(qWd;&E6q>N%D?wUA?@cD`lRXh37|_ zcOpskiyfXUlaiX^8|oZQ9>#C=YmXYx?A({NgDiN00So6OtXsAbed9rp?Lo zroN}~$BDWLRSq+sQC&m|a_JTIwQO2kBh^@3r&@<1GHDI(9?HYMNyTo?Z}NvhDmbc1 z$`_D9Zoc30fY{C7askYNrM+S;4xY0%2XFQ`>MYl)W^YYqI{Tm0w@T^HJA{8%O>v`jw3pG`D3I4f5q zvnt)9yvThApYoMHl91J?HHio;RZ-QNrLLSQ&nt7SIpO))b7}ea_87==x2)FjS2C|+ z{mPwrN@4}6GsyOGK#BU^op@gEP=}M1@?;JR=DM-}9MoU_og)k65m~Kcm*>t+E!ERi za5d*pC#iJfsw8IW1X-1(b7o4rQl9>ojBj;UapQ+Hdofc^R_~sPJQ>;>=q=BzS@P0` z+SpB|DrIKaYpEPTC2jkF5+m38m~y_RzO0Y_M-RVn(HfnyFA8z(oP?yNmT4#s25EXLeW zzUU@VDL~NFoGWsEa(CTGq=Ku?T^?feYHDK@S9BGhnA!Yh>Pf(C=ABolhc#73sZ>Sc z@<6Ar3;RmQfH`T~Az7(yh{wKQ=oPpX64W5;NhMMK)Rir}GU|zE?$&x<81+&RcT%@v zI&s3E2kDC-iBeC!C(X#}i9qFRDyuSY;QD9V;OAUv>C%s|@&ut*bu$xHmDg*z3!NOM zkcSS*7bLrCe3RIwG!Uz;lxi-?QU6;8dU$hHUCriRjaH8`m3n?Kb-O$ps2$K1Mvyt5`X2Qtxg_##n7g_F6B>483dG3SzJ7IM4Z}+B_a-ili zRN=FnOO+Chcj-Sed*MHmPI^-ySObRhQjRVdJeOVvNeT+J zOLeVGD4mq4cg98cUNd{C=RmT54#Ux;^jY(RsJp7pUGj+1K!KXZlhS009#!B?1@__X zyg&}!{L$^!3j0)54A-Yx8Za%Zfu^S|vybQeZ`uX(?8PndSY4f#E_55;H@A$H5;*-P zHW`JQFP`l%dajLoTb%MQ?f&$UD{U8!X=i5&QG3^`IWJ%M(#mgpCp}abrFx(ypVWgK zld+h*3&yiZOd_T3O`u|=nuq%9*>qG7gp|FJxOzr$3lV$I{BOpy=QyUE&vgE2KYJ6z zTHMu)r=BrjP65>tw|C#ZvLplbz`j!5B$g0!ET%+eLp!#GQ(wegEC$oc%+@lA6U=bPm9O)F@3pP;}q%%h?_#wYTnHqX3cls zf(*bDEMEf47&1@jnn~5ZaI#4=m%?|vhVr)JK_y|o!n#-x|@gz32r zjpJr>=`N+m++-(Xl`;G6Z%?U^aj%V&rd`wW$M>W&X78Y9efJJ#OakT(re&vVzWWv=PEW9W2_<95NGNuG>@RXXyYXLJHfbE0JuCZ; znK3@Iga1zA^aRs?PR*Q;duubEOp}STnPaW1#Hpf>34kd!>E@u9LlsQ+KYY&)>7!|6 zEM zz*(%0=I=!wn3e|hNaeLpg=5r<`;zRO!@2`2%}mYe95TI5_8*+4l{;!OlJx^iRbw0v zjB0$ajNWzzmg>9jNl12oon#y>xU=Lhc2ZlbG^CF&T|qn@nQkCmK04h4W^|cevx&(= zon!lByR;4ZU*E_u3{@%(8PbFvmH!7)g=Y+)c^^dHj17m)JpPOcW`1K|U*r1Xis_5Cg{mfiPtko(bUWaUB1@pA1wr-&rczS6u4# zYHBu9wP81n>qgEDPdp!_r&X1Qd%|R%3)mC?$rWf}Maj*6*)FcHw*O5y7N*sw^jnGP z0c&X{vYV>M`D;u119S_R{vpH5vg-#S{#6Gd>bT&^Hk`_n|IHcwezsfS$`B;;O+(eI zZ`ZDL{^2ATCst&9LC0G?YrKDoR9!Zy_pqAWZ>Giyra4!iN*@OvTC#N=Yo?vLih{&SXbxRgcz3{JYnp^-!GE)}WmTBqgTW#8;(t+MVQH zIcu)7y0zV{;_TTwaKJ4x*RBSwcWzf~i5gS|pPc;Lo}|I+j&%rj#2L(L;g%VhDr7ITOiJbORPca_oV#B?}!)MZ>FZ@VE$}zeRZ7p z^w+G8yKzEVV3{34zmM(?_}3-v8W)0g1K%3u+N%6ryR5r~756`u!~X|fZuPf4rnj`) z#q{b+&E^s+^$#AK(-P|XzOOoUVg6RLIoJu6yV^LRuKQYL%PU=~PwwxXe4Xsjezb1+ zYwAv^uIE+HFjLgJ>3fq|cve$?ZYC!v3F&v0>SW4KX%UbQW+&a6nt3}(za(O20bgHs z|1HXHi4>l!z}Ki|t?@ngKUl6+ktyM6N&lSP29+M6P4km9#OoMns(j^IB7JcGeFs^BzRQmXbUeE{_mYo;~}uDoi8@fFdTUm0zD#MSIt6=rLd@;Q(s zeY-uxG!dDXGY2*Ga^|0w5jYdit$l8wdMSLJ@VX7qbWJ70buzDcC_dkEjwNp`$&%{z zW6M;u`pZ8EyZ6nlUE4+K+TVPCKCxD5%L&-}t}FdLnZHQa)v^c*raO9m<6S-T<1YEdjeevl#QZolKO#SF>Df{bo=uqF=j1Py-#h8? z_M_Fj2WCzfv%-=2r#IR=BfHIyXXf7{KeqRb);B-gm;ZwN(9V5hz$||$|6^Icg|mVE zW~ll3(}JDl<2Sw&<+)J*T9DhSpn#vZ@SKevq-9o^+^S%2R_NqgK@XlWtCY7Y*st*+ z=v6j9@87E6w8n?fPt0b8Gg=iq!U~-|hp?MjoU2~&SgV3}np(>}pZ8i7{LEV3doFcf zbEK863N~#mzk2UF<)itzL+gTG{JfPXAWjlD>twYq7$xiIxyL>0IZ@y&zANNCyoz#a zX{L*;e#m@r)lc4_>R6JtEBj)qA2MA;b$OcnRbAq=W9h_@wpicSw8c6`r7w2(?Y$!E zhNP{mZ-iRh#0^lt`4WIyk~yWRpZv*4Ey|Qo_#xHwwC=udCrJZD(6mm;eD8gm{&rH4 z)JS&=$y@9bq80K58TBz5sbZ?HriG*jbXHTD~zx>c&jwBbu znm(aqx5-mWtdWH?tmz|*ibfWe%owIV*CVruTJl&BRVSss=p$z-S5-c0ljNh`vV(%L zMWc6X_;gY%VSgh@K4@qEDNh7ys_}OIY0>Se)+Gi+Q+58|)THc8Gs(+mHe??3xII~z^kY~>?j$NB%|yUc)Jl3DJ+tuu*_d7rRmask zk#N~(8}x4}qv)I$)bj$9UE*n?BllW}&ER&ZC0)D==U-@2w9Qz?|0dS4d3>&-5@7-^-FRWwI=kTNaWzP<3}?(}5wv zN;S!Sr0gK~u@j98AV*Nig-0Ay1eB+3{2~yFn&0 ziDye4-^}DKE7Zw**mFbiya3-88e7uLJ=Nj%zUH8hqK1kw0Fts&@*cTBy4O2%2nR?C zQ2|RN^8)fWx55)pzR=_e)uhSeTO1^_Gb<~YEzJlj&Jy{9vb;~TK?=$7<)X=TaRSD3 zkjeBtfeQ?he>hi6=Jb|?zS`h1_4hP08@OC0$;+D!%z&g!w&#R{e@Kbvy+Q+Jl1Z7? zCr{=S^aQ3vrXVYrJZ9`_gEK{vlN6WI&dz?#{99bCpfxD3fR9m`i>E&TR~3rX2CbY- zzsMZq6r;^Y$Z2vaO{5kg0M8S0omU%b)dg$n3^IDk+!}l8Qs!1+>TS8ODx2$}=2?@a zdI|zc!Z7JrmHE!6ohfcJ&805sEFlwcQ`Fnpjwkc+5N;==yqEZKX8qN)Il*a1ogWNCv!D#OkR%s#;~!^*^Z`hSWqK>cf%A z8n==!703x{WU}-CN=0%PzK$c`jBIFV2v$c^!C1Un=I~eb^F;P=?tuBcjbz+w_E{bo zM^MMy!C|H>wJT-zzwNzx>U@;u_G0zArN4e>?_q7e=3|og8h^?sttUyQ3h{h{r@#83 zw`4ZH8Y1mEO?-*R&dlY1_ve!X;h zNH$*|VbyZJZ7E+ktqfY>YBS3h_0omTAhcX-kQDaia!KVa6Z!ayR6(SY%RHT`!Vp-b zOAvdUP~*|*_Pp@K9RD{_0@SOrAGzUyLk zVJ?SU>Sn)pWZx31fNsrKs>kYT@ZlkQ4ZX;-4s{v*og-%*waBxIY!f$MR`Tp7?md!Z z74}De>{VouXCD=zXhpbItz)mC7kSpvEq=ar^diqXyeMssWbcPXo;9c+N}dyvwd^(Q zMV__vJyj=euVof_R+3XNm&Vx@i#%&Y>X<}Xec8$0jauYcMP0oCGO$7#Is9wtW$vo$ z@LNZAV0dV7$H1E2a{W$=>LPT%8zf&Ys#?DyRE#1A8;? zl&JnS^c;oecYP~ldle`tnB~y=M%kZBOQxjOtaHNwGRhz*xX(trkcw* zuKL-Wl8n1;h%*P6d`rZ9!fk*R4@KlrHyn@0;v?j{(t0K^JBExPYhK@Xv^4JwugCr7CU`PX^G|$Or z3DmC4RkgEx0xu0Q>cet*c5!R25|7q$aLIw?#P#K}SJeO8*9nE>>3WgWgNWEX*h;s! zoU)Go=1k3w)vBK8B2NmmI}nz%$xA&EMz8i?iZc4(nIa8EZVNA`-iaxm{MWMSD=5ub z9HRM4D6KoIy?(OJ-}&N6@YnT~vomf=@--ccAPp0yxgt**DaZqf^l9-oB&m)ka_74& zc4qGR>J_m^-DBzt;e=FLvI5eA#aGX${xpQ-JDB>f3cZm5aK_e$iW z;PMi+StLs?I`Q~l4e_m}0;I2msUFA)$t2V2z;ZUuMIrS1gymeE z>*FkSLqUa4jbf7>Nz;MkGEIGA&D@skeNtg*-_$`>=jv|hs}6hKQ&e|fAI9A-V{qMo z>C4E6NfTB-sr1SxFjCQgo==GM|ZMtOU#+tFKO9T82=Nx4$OZjN97SyA3!x) z%Cn{Z9H==(f3?w*OxJ%7Q|iPjD%vwTIT7^F_#7rt%^cV+ICG_Zk*ccc4yJS5Zu(Fw z6IY!=Hdi8_?~BHV2K>H$cl z#w-&hJyQ{w^s+Dzp*_a@Udq2R%--yN;?ldWlfW}>Vv@Xf1A9@XBbX4Bajm`E_?Bnd zP(6672R-j*o~4;K(#h7lfj9HYcs>;}g@SZtxZCKKq1mzWGW(}K?n6EChW}`cVV3?( zo7q2Q+RTm#nYMF&>tou9ddMh>xNhWOFwhTFpOAS25hJVN3`Ip04A5t3VC9L zT1#^C(m>JF!omrK(gkP*rjMLZV*VUAp>RU+Zez!=c-+VdljJYAnqWT^sGS5UK;~u1 zx8%%qrjOnGWjW?Um4CbOfq(h$w5d9p^KolmZtI>|U%o|_iu2ee$xcq2q^0hqI^Q*~ zVW@3QwM!Qeioe8%=nhf?E!NkbRciXny&gflTQ{|5`9Ojt!@VRMRPFF)o@c7gswYZH zav6>(4YKB`N|u{w99QFuEE$ug2XL7RaivtmsS>N}7Kv8WrWj~Lhq#o(aT=PO*ypb+ zuX*9A0{BNu&dg8dX<4)`y;_t-n+wt6&)TaiWpXd)saxtKdioRfs4W9x?MH3-V6f^m zoT+^`63u>9~(sgFsrV zQw-*2AcC(>$Z!_5n(A}%u4bN|`R27w;X3zppYrW~GZPym;ma4u^cRyo1rm?#_LP!N zL8{`DGlIdJH?tGoi_sCyZtZKOt-}v$2C(7!Y0T~clI%s!kLkbY4sfes(v=-l-G5mD zd;USzGpRG%9>n0*v`j_N%!=hckvJV2YsSh_6xThr(vRDVlFS+aI_f9{D< zaSThYWY>}WXCN2G_lj)hsl)XBlft9vkGiTTVe(w=ptrH!o=J=#G(KSFcXBfxa4q&e zIMWr;%@B>hQESIAbs{E?+23l*bTaCK$^?{Ek!rbR3!Urh)>hR=p`^`%dn-fh-S!ZF z71XRCpK0~%LtdAtsF7_0bs-ti9CzD>odFUmqWPW~bR?JRvKd)4Q%!f*XmF8xLAV=4 z6L~ppx?TOpBZ85r)4zh#%{jpO$DvlFenynW?V`hwi~EJ!Ao9=0X0-ste68H^T~8$Cv6@ z(D*oZ?-+yeWZZVBQl-Mu!S?&vY-3WRTBStR8xyXOfy^o)HcE%A-E>;yS0_F4kMwue zcWVBMI8lbJ{g+3_yBtrnQtR09Tq2iVV{nEw)QEU{g&p0NEz`y(x6LU>oDi^tiM8cM z1xE0Xyq=Xj>e*|m75%ZpyNQnCYh3+g5@vfhI+JVM!Xbr@JJO8srNyEt=caj@t|fXFK;En!C-sbKDJ6-yE%rK4#9AhX85frrvM2 z-Ej@=2C?!~q_(n*2WPiwBcM|VOWpdZ%Ej!h+!Z`Ceyc-Em-bYZzS0h@x6!SK-Vk{9 zWrE;2C2z%7kL>zS)_nC5)>nYlCl6^3^$pZg1GspzQN|+^m&}`zD%$-$9;E-jRe;R^ zNN+t@D#B7LHbbc7wa2lAC29$Sf{MnDlWOv)NmIv8DVk7NA~oNV8B@kmGoDZ|a{Sl< zg(C~(U%N~xnmkVWAA(G_`{&ep*RYR)+hi`kB0Ao+NRrj%`(8GYq}RVkt#z#iPuUHna<8pj zQmIHK)jV?T;d4fr@r)&O-l%pLnX*G(VvuoFQma?7X3(5b_Pdd0NAi9$yHd@e)@T`h zC2ysvFbA(rlyqq8`A^j&roT_9alxLsk&pv6s#w^krS@sb z18Rn5NbYRo1LU|5%xUd4av0TFE2XluVC%*inLN)apiMQ)Z5nm=#i3+#yTx~s1X#7A z)uklq$rY08B)be(hvVLwCtEp11^@83VR*vB+aEfqu5mL)w(LeG1{^_nOuLCbHEA~_ z%y$1Y$M;>5#;qOpaA+AJm!4Irwhn!%%w_VnCpT)k(rpus3r^=ss0*&w(P6M#Uy`YK zR9-Og^@8d5+|mQ|$GX8JV#^D4(kEgDlGsfF>$6Lu$^SrhsiT$2G4)+{vq|$~TI>i~ z6OvBjb`9AcRXgef~eH5s!_4143agwF+b`TDs(o$z;qdNqb8!Tblx3{hIwIY^Q2iq;KT>JBMe1jaGmq?WPi|BwVRR+c|Rt*Hd%uT+@F^*aJZJ# zB<$ymW;#{%1Hpf`168VSI`3|7Ftt0vR~{O9pvkm}c`TB*6MKFAOafeZ_`T5utLp3yLO)iLg z3rvT+=`x?9XCzAGnl=SVqxyq!881MlPsf=ZaV6bP)2-&Sab}x>SY@g<>^rvl9$v;{ z%N%#C?EPw8#zU{>t9WLcF`jQzd(U0Hu4f-#@*Fu{sdO4t%#p$EO&vS^1J;aQ<${>H zzx{bU`|jD3$gJyPc}%P!%1|4rOvy+=)ohjCpk*I?eX-0P`X4Bk?HleZn)!;CerMGA zSsvGEG96$q2ud7MvDh>Evju}3?akMw5mOy*%^%$DLuM*){jGczQgWH85-Lq%DWi2a zJteM-Ha?El=sVOhV97hWN9Q!_{N0!qWd!Ef>+^yCk$k}1Z(lZ0A~kD!xp}?CpDQ?{ z7*qv94`YyabThe~v;az#nz{0&%+cA$TIL!~ApC=)?N*28dOp@N(=bO|=Xr*_N+9!q zCz6#i3L_Xvgp$emS*Fgl)|~~b&q%l@>6zFc>lbL0i{>izEI?=yx_97G8XC2wzZm^I+?`B5(?ece%?@4WBKVF~6kp&z4_0*uTgaW|{TN z{B~~s2lCry_HRTJ`={mktGqv{q0f4&f>x~xc2{4|vbWR2Ld~zmtqRWNSLZw>j+md$ zZzbR7@&-nC4x3+}XjSlm?^oTKV}AXpRlzELbxx7SVDnq6)&)E9MXt^50NKy3=J%nk z3rhICqy4+7rkbCpwJu2Vv$JbrwfSvs>w**b&ACP@3Ys5JY+Z1@{HVV2I?5k1trj^e+NYYN0Pat0itsR{!)Q1OA)EKtq# zG{dSn%GLYOGS|AijUQlg_5jlirTsEsfcnktjME(;_JvrZS>1P#BaxQ}+`UQpV~+!! z8r4%(HoAgqFrj-hEx-D_+)p{ls~p+pK=Q>A36ec*k{Qt4MqY3CYFR2;8>x%PU>5)9 z9-O1DaYw5P6g{_kOX);i?Wq19<_a=_YD!YJd75hR^eVdMYdW!<`Bh|wUC;a~lF;1w zRm?@wGpZ1c+&(EjUew->2yPW`>->TGqecGTDB&7^tjKIk3HMJsm8(zb$*Abre9c3O zxN|pOU&O8dq9pywb$^F1N=k;dW?w2YUpPw2gisCfP<<00om`s_57~+6j~05)ewr@z z>{b54#hwJd*$>z7CWgv$$|w)qK^g&`NSLL8|D1JL=&s|u`d>@9r7r%OwnVz$ z6_{*ZnU#hl?joZXt5eN#YiBHynNG6! zU#F`okZtc{Eh=`IrzKhAik&l$T+1tVYT%UQK;F8SeInj5ORP7Cl}f83@(outR9gQf z%d&JePAa#FlstaK=QA&IO{^~bf9$H|IVVq^ z@@^=6PcHSXT;qWYHldI{OOlc(tK+#Ygx3j!K=PC7ac$TcBGv)fKwVnZ5d6@s3Xo&0 z>U^}Hw-Gbf8`dpfeqYs(d2|O=3Bg?_C0Fs_E%!>Rh#B(ML zjbE?i63kj-Dybo}IuVHFT*ig%AXchu0tQ)2Py5I+_nF=a#=z*}^J~bhRau#FF)|yR z@iAz5e>7+!^IMvTStRU?s?%N>$N^4*HE@gdc_N96APrDszyXK~b+ORgUj{|~)R~y^ z)nVZ-_}*a~yE(CZI0j}o3DzPxWQ*`zad&;ynF}vrRlf;ta9*NICA^_lYOj{X6&7ES zQ`oCN+v=IGr36#l2IVTHhuVZX6sA~JU~lf^vW?W15@k#qt@TE;rBsBY50g^EHttD8=4q6RrTk%#;;+{Zl~C@O zLi`#o?hXBL`uqi3qDoiyVn@nI`+((3S*Fr^Fynr7M~}ZU+{vv}p_z-VC|A@QXPgqG z5S!FM7Eim`^d&E73p4#HCN53?N=uh6QddZ$ZEWF>>KIMIUlD^Q|vP9mpg9@I?Q%1(uVS96|hv?W@>l z!k!H`0U<*kC!olrD9Fa`2EjN=>|mzzyA8*$xrj_^ml@Fru6R36yMdc@olGv66=&{C z!K_FLlI8Z3%{v=A?+X#SE>>Q$lM|B(gtEoW7?|8CmY7^#*6jAH%@-G8e6Pgx!myL9 z`8lOnkW`d;;A}zLG>!${YFUFNL>qTyX^^&rLI&pnPIOzsJlJM3`XXvS?ss}sJh$5I zmR|HlgG=Pa)(DbN^P2B))|<%Dq$aKq!m#&Cq_WgsA_dWl@iLE(RmQOdKh_ezURk<* zQ~Vy38V$GG9phrWLND-(og9mev8-#(CG$EN?(5;oJ89+=;3gN5Bl^eI(FH^1^nEE9 zGHFU~;Smimxsc~2ShK)7FKgyVmpOl;tR;+S3V0rzzF_>r@ypGN$|1)1i)Z}aDB?pc zwxlcuQUy0E{UnNH=EwDJJTb-CHE-Ow;~k7_pKyXS3KA!|@zd`F5-A`z>KWLiu=vHn zByk5+t8;MB=8e2kzM#ZHAMR&o?d-=)KPp0iQI&F-2zvVpwhN=Sre`HmLFmjH50#a- z7I3NirMpqQrsEpmKvo5ZVVc;}`F>uf<>~c^7`X#c?zD60K4TIfjJ?F!08y|^(~5A_ zoMM@`n_Y+=lE;@q^pMuV1#o)Lo6i3EHUt7@Tn2}#CXN)3VJYa@Lq)$6}IZv!&PbGRcV0wp# z&je9)|9JtDo4-#ls+9L`0zrX=bkm?HtJjb)`lpD~EV!FPVt*KH&MMbxqWVb@GwNG^ zAZ-MmiOewzh&nW1k0`n0`KNs>#a$m|%Y_KxTz)A;h?3Q76Cwug^AjUe8~8j0$+EVJ zC{znXbv4=c-MF?xbjt<1p~^}g8C9lXMl2Ejv;Nm{D$(E+TBkYi)sRYxv}wP+1MEEipe&9+@|PL z=oUraN+&H@0DqV;-eMi91&vEJAy=d(_`b#*O)`-VHNKU5vRj?zu==w)gEF5f&jdthY*^TkbKCg522H#2H7aYuN(aYXx&hB~lRxuQC=BavX;$rW_ zrSQfXT|_^1(j*lWb~%ghKp-6?ImWWWTJ&iBIL&=wM_50nOi5zzhN3TrDG}QnOecO6 zP)-fl>x*;ihqbJ7vm!)iYa`}rSm7l=`bs0~Y4=`%ilT`-2JMqZr^o05JRhAPb^~^r zK_3D5I5z>Y*6kqZ;LTrj6r0(5N)Sst!Syn+vqn!7PpuQCYkXR6lFwX53WAioxjKXL zcC(kgz2g-2>-tVy-*f7_HVYbfN6KOWg$Mq*|!xhzqER7_z{I04G>xvh?#M9N*qjX zqZ>2vQzWrGU|$nrezaCnjCdyYLJ#{f==8Lha&9#R8CK$_+3z8uZKRTg542F7EC9%g zhg2WIBRYUbbkJ_Js^R0nBDv!|f z4ht>=&BO6qN|1RW4F__P{_Ly%f*T<-KHrus9N~?ci8uf9D_`0Av#lSaP5=geXjQsf z{}3;}?!dI?_U<2V{WCLE7b}W^I6M+7y;_pXP~>R|o#Hb^p3lk&!wnYGseaS57f3o) z%T-?e;eYw-7e?iaWU7?4znaNZUt8i1T`>zAlE?UyiCVdVf_!L7jt*_cZH8~4`S|si zUUeAGWqD<;aPC!S=L#>5-??nA(-VCcQ<+wlArzOjAyZt>k$Wx4b4v99!#Ov_w{F%d zYY#W!ff+y>gPDXEnfNuc_MYJGG=`0RB;d+SXQMs7g8$w&Efmh?eb0;uQfzl40K3g27-`bh%kAe_kLDNq*(D`|M63Dzt#>ukdf^o{gM6|AFs2yjNdd93%p^vgYYfA+pUx1WER-JUffo~ z_N6m>*|2aE6y3zpU2U&RzG`sJfg}dA*YZ254r`J6vK@N=FnO!jT%mxy)!#`0-2uh| z`a3BA>CsNxm*4UIYxHs(isw?b?0_#QjS2FjDJij``Q0oE-f8Y!`j+^|tc}-`I(~A( zE}udW$a!sBbF+2XrW!|zdo8-5Is@EGh@9aaWM*p_dB`Q`T0#Z(g<*^u&l_hL6Qo{C zMlV|wWJ$vQ&Tk_(x>`PfzcW8-x7zp&d(71bOykapj}=4CyrADr-3rONY8>qYh)8RAFnx~>lV+{XcX0gvydY~h>NWQLU&>Otm| z+45F+SNY`mXhf)heFEjXPIu^wO7`5NN%cYY+?u;8Bf)yKf;8!D7#k11)&4pXXs)Kd z!0PquP4oG)7(ZndKcX1xj5OGH#P*txD_SIm4=5l9RaF1&ER{i}WP7cAt<@glf()=P zLN4a|qN81#z2IS-pSc1JD7Yj8o{kVCg{Y>DlH!K8yH zh#SR`BZy8}sV{R0ui#fYY@rk?jZO`GSlq9n(3aWIBF>D3`SLkzMuGdP!DbPgk+ME! zLLlR}7$xlr6TZjS6_o_WvT&5*%F?_1=hk=pYtBFi%MRd-iZD2-3#U~dM?vY}6#zu; z{t7?}LSbPzo@9ciHj0;O98bAKCH~YD{*_1f?{41T-2HgtPG#JdBLQMMHc*QBQI z5>(JZPZ4V&Ml4wuy5KID_?Lr;3sGh7$@DLA*&;cZkf=I*v&ZqwTgc+_e)jK#?;7r* zjKXzUFrfu*SJ9SB{MmFUze2;6Th4_ko*Jl7ZemI^{__^r>ve!noJ??jZw;>ifEHacx#pQ(rM zyM08R2)NrGg31B4a4iE?T2*dl4ldg!piKG_IUmh)=S2;%L|=;`7xDOwK<#CB5(( z8bmQb)kn%5>h`h^qqr}M>pBI!$8HqDnoVk9g2sDkJ2yR34t>w#OlRd7-ie9O6*Nim zLQHXO{_5{FFx3SiRj{3uxy|I1!URzg1x81rttt(3G=rd#Mi%D^3T+wfEW!ugkj+4G z(Q}Mw>cB;Qa6-;n>{`!x0qO+@s10Ay5}{`B*TV?b8@*<`8<~;>4G%^=3IEqgxL^xk z4z{3V^{Sk~pnMU`L7Q5HKd4{m^UJ5A3#G2jyq<-5$AWx&zO$tH1}Ag+%(jMPs(v0v zHX9d9^vkhCmB3zgi5iqIVu@-~Z_pBjkZr#vyUz|miR3iZhby%GwA~ybM=zFW;}ECl zE>`B3V`U0mz3ReLAYa6~l$I7*mgnAKKYwBSYg1jv0(7V3zmH8QypsP_ym%f3fv1@ce7uwrIrm z>Mytcx8#*_Gkf(fCAE&XBLix0{?+#Hg`_zppmLzVF_2!$6K~rakcY*-6&}Tt2*vJ5 zp%O}kXEq#sHY!CbDyBTbP`sgZH0*Rc!%my2an62wO0eQZYMhH;#s05MY8)C2^&9~V zoyb#@9*2Zoey?%NjM`j;G=?6HPLPqGc2_Y}8{f0{lIBNlJwWFElY%zD8Y=+`48go+ zNAm)K>*k$(T+#vK=m~7F)GQFx*R<;pW}2w9{p2`*qpSOSBB0kPtPB|2QD|E++j!c* zZI_6n)}N0nxL)AK@T|{UgN8?gcAH;r9N@^LenIM^8?ZWClbMv4vZX3s;{X-R5$gU8 z8?MJ4v6XaSZq9i5g8V|}fx$CAk-?=cg>Ud%UexkaFs3SwhF|-P@%^38bk1ml54W~f zLyU`rqr~&k>-`>}y_rZPCkb^eCP{4d*bUX~6CB*49m@%J-`(YZ3nA(Z{1V;}E4!B~8F?@H-aF$hXG9|&SYZ{AkcGSj8_>(jh z2?OM?^86S$D}mqT3~M0_#WWv_T?y`v=oM3QYU1_Lx^q&c6IqNl*^8F1!Kz%X=mcP) zJpOFzNq3ZaT)_dAV79%S{otrE1TPTGn}5p8Zcx2&mWWpKQ@{rYyOE7>fM|$_?}vGe|G%uQ0E>jV_YlaZl(J1dn8xLsqOh z%CU=5bI>e!#)|GcGzPcLRg;KKB*EYA1S0ODxTzIp{VBImu53c zrmFLro?Y-cjpyaisN; zS46t5$0}Ht6|_G1S6aKsy$it>oz_!}O{jIC*F3Fq_@W;X3nRvCyqBT$+est|M`zIJ zU>tWw$Rcv0ffv<-%5y?_QFc`dZb|5Z;%bo*1bxe*Bc3+fr^Drs>@$>4> z{u;_)V`2t}Z*5g*r6?%A_UdnM-N38AK1rjq5;aLz{5xYhioJe!YX<txjYweA}9sD2zMd#l5tb^TmWL_Bn#1;P&* zXLjYqB~{j$W3rT-BiqI^R*~JJy3(Nd6;yNPby&&PH49}>OU$lC=_(nECE^nbT;8tT zhXx?FGadK}Y#c=6G8z+QD<9#OQppxUxl2`n+o$%)>F`-r9UhIKWikx1p|&_^H)4z% z?c21figKCt8eOI&duFM_c&;bQ2hHXEPH)*JU_j}jN)Ysf&?quC`DL#Lb?$jkE5{qM z?KGxn4W9amJ+v)@hmqz<3~E91O3Eg!CnrU3e)gG8R8VLv+I2(pBg_!@Q3-fLgnOkX zTh}Ty;A*>cax35lx6jZ13Q58Ahqt%h)65F?kn%h)32jL6uOTWHCqHYj794aAA;vfV z>J-n!MH+<*sr?3dCPez4KI`@ejirkiVia%a2T%wz zSPi(K6q0t6TP=su%RHS#E;$LN9?~ttGh7Kx#qY9|n+eIskpo{qZXB2w6?kOIze&`D z`iwJwbL+Bl=Jd_~BJ8=ujlrM4Vf;Dt7%ciPE>C6AJMeFO+<;wSv)7!wyEuUJ3As8C zhG(Fz?`KFQmm&NQGOh)C#Gte9F*m)|GAt=jm#{m=CJtdZBUlsE3_WZQPI6D!JpGCe z3bRvQ+Q9?i**?M0hH;k|>>38y-9F&TD*Arb##J6@!uV`<+ncZ}KWGjGjA~;@v|;ZS zYt}U^k7rpI=So7&$vux96pezY93dI17>?P$vkv@w`#3M0w+}|$8)ylGk^NwE@8buL z_OiA6pJqQ;+u2#WzxV0)#kt5U*4t0oJ?Rwm{cZ=n#HbD$J!m}r0|40G*jfJ=HP$}d zytldcDXp@1H}~#u?CxfFAM9jn*~7J+z0LJU_tti@hmUq1KG@yB?IpVyA7F?2Gsc#7 zt~Waao^D_cyZwFF=lR`lTfwaF zPF`OfH4hG9nYBHGI0@w^OWdH99M@~F?hQtXS@dJ%ydh1~4k^b(NEFUUp9$ZU6R8~R zcsnQD5!SHW?_H1%M8eaon2=DuFB-MJO{Im}Mhi%<2tm=_=Jem}_D8MIGxVj#r1XuS zLZYRK=}SW_s(IS|^i-j!OOR50T0kn+cA8FFf{EI7SAaHcP-ut(FRr zGm7%Ek0cnc+oboccNJT7+Kj=21d#iCWm5w_$t_K|iIA7CfbZ*1_(EyC{Q`m`%k<8;7r2d1&YQgmA#pSq*)Y{nxim z@KFq`$YLID>B|FC&H7ylXQjpuCIw5AEG@uTVc{8T;L4`-Rie< z&X_D^X&EDUf*2AM%&Vcat@V2USXaBQPodHhen}NrxNVGIsKYr7zcLQt1sqbJv`$Xy zt`cnG&YWaBzq&4@_9I}9Y$mdfSrzF%yv545uNIBi-biDg8K{o571d=ycm3`Yusj>Z zNo+4_xE~>~mj1c%tQh%eyV=2|p^>jpTti#NofIY?&7bNmf$jadf0r@(^E6{Zy3SA% z!WOX+&ol^w`fK|s8iej9^X5}r)45q=^vDS^$DE8#Fnf*WkrRPg3<}U-OMnK@?Hsqe z&(O}n0q#;$S5{}J=8L=sqNq2a8B6=r5MXV{$bxIx`UrvF?%3RI}&5_rl z)i`##GSu%RAolxxxF379Y*%889LZcXDAh*b)ur76XA2roY8f4J)bB!XQqCzZ2+_{z zs={`kqlTSK4@6BA1yE#e;sg+dpGaQy5)xDkwrd z8`u?P{hy0aa#Eo5?DqS|#8=SL9gx2s3)WeTQ%`2kD?#$4Ph@?`t|w(V1(TA5FG4>uc|V1j{Q`+ynx;KPr!5Gks6k91*KsN}Qiv4FA}0R`or*mNc}%t{1-NXKpvCsn zVbvc*rHeB88f?K)@-v$lcORkfqWTFI>2yCE4N zOOB`RTM_||Ku=hO!_tOm<=A-OfCvz23uFlKmr>{v^y{a4a$KSPsOszb_XQv<*_!_a z2m=f>*J6rAVXgRf=nIhx(z47;N#$HrFxWWOo;7f9Q_w|UlLDGdl4_wP?k(6m$Huri zx5f@S=$*>0Bca~IOBsC9NH7jHo**+@g8|s)2Xp~Y3@9N`rnobY0QfIIU2N{I<7-Puc@oghd{@5mv{AipjfaQsGTDH2_{J>hOyWL5Gkm<+t zEtKw%C9oXjC1Sgg?y9kKqIt|Ki?VCG>o1l?crS%UB04y4_(dPTKj_%E(| zhp%g1tS$a}MI@}gP%v=>SImkidb`Ap(QE)Fq6UXB(sWBo6AAnjigTB#mJQ)cYTat7*2gc(A;lKvs`ei9I;-d(I(1g-JX6D!mz59O_o)@KE-Chp`;fTOXE2r zN_n^f{%CxGXtWIxe)F3q1@hj>&5@`Sgx;(TYqSz9al2|q8)$Ze5@exU;s&-wP?Iwl z)nw<5exs;+e+x*&{&SGW#^B)Uj$b}K>iIU+SIi0+B;bltD^pJp2E8s+hNxRZN_zYl zrIBlnudElWVX@p^!^iY-3Q0rdSQ>pHr|%$U8zxcYmC!)98wD^)-&tp@TLD|X<>%n) zhV8+@Hj$iEauEqeFN8T+N2ywbySSedQwy_u@$Hy-l<-t4@f+|>JCc#=j8bGz>pNQd z@yEuhI6Kz$K^ul0q~5NMmw#-~LPTE?0Pz_ci-W5|^O#Gl;SrOoVmZ5!kyK{Qq?4`8 znHJGGj2TOl8f@gyQ7G=x5K!f|9@z#4X9G~}HE&D3bdBs#G(2D5pFdN6(~QYw#_lst zrq0n9+7#PI7$eTHN((QXvUr*O*JoQ!^#ic8m-IVGxW29!5hJf6@0CX2OzV$eDWhQ7 zd$4^^d=YYdYm%kZ)|KlfldYG*&;Zunz{P+dmAvgY176N(YE@H|54*I9?Kcc+kVg#K z5nT^k);>iju647jh$1K3VuvwVi8EdiImA6?HS;<`>V>_YmH+Z_g`nZ@ zfxK-LisMAO&*77yQ8{dng?v0#KbQi8UKKT;H^bdD6)|?sd|`n&Xs0fy?h-eGHG{KW zP+v_yO&N<@m`RuzB!>hSOn<2Bt*d9)$TDeXrX^WSf?yXizTm&HUaGGaBT8(idp_Pc zaWTp|EZU45ZLou~&4_~Foa|J2ux)M~w90x-8sPTG1sCugOD_~i5EhzodWC-QC0xU1 z>VMN#-786SqgpHwm!;|;EL$t_cGSZK@5lN=@Adqhu@z!5L4U}5uzvQ9@?Oc_u55jR zw_j7Ut7@CMz4~;khgZKBDw=6WEQ?m;CtH6XMZV7SM$vj>@BZP|e}H$tGq#58^?xXd zKE75^g6-8`Z2b=bCtpVP>R)XAuWYcmob28IzV(0Ev6iv-41pR)Q=XQ)o;-|g%fo3S zAulJ4uR`$>85%)a6*~^YpS4rOJ|Uc^d=lp7_m*%R<~!L% z)K-ot!HcM^H{mqQWv9k$Z8SXU532b!oIcn_W_Ik}KN>Weo#X7i6Pzo+mk*$~!xxX> z@ssyK;2QAN*vFM5dN5?|!}V?4&4FFOKFk4)=I{iTwSLPZyb!fJ7VU+gx>Ll}K^fO? zu#q;qFq>r`VjbOMuy2c;&dDbTr8hmoc;tkkj?fub9;HcG7h(;^CRP zlXD^ag0cC(kzK!jjGi8X#-)T%32M}eWTMsilC~m5SitrPkvXD1o+*HFgCvV{>L0T_ z(}hco6chLn`Ob(Ds{}t1M4)2uiJCpT2N6R;4hpO{5b!UaJeRWK7FYu;3GdyYhM(dA z5juv4AD4}-&gx4OM?8ff67&tjWG=2>=WKvmc;RcR75(eQwH*fERE9s=`eUdQzh5d8 z7NM2;wjAC4y>cm88&>3RZ(RYPa%-nX>Q?CLRuzT*dKnIh*GgR9dK)FiS`uosB1>B} z6#04)$j^U##!K1%ro8)R9G7x`-`V;*sQj%$fj}zO!1uOR$I66hv@(CX^#RKKb^?bZ zZ!bUGTF1*v@ugvRi_b?q89j#me?t9i#x%(LX~Q!4rOl4KoHFF{Zu*?b>q0l=$#}2% zcvRBTptk*PP}_K;E^I|7r%>Mh`EO{1z2t@U@!U>M}TVyif1At@d6^g7u2Zt|KE0shJiTY)5&=LC<#HGCU z6DJVTuv+uP7v&~D@><(OW&KioX^7yheJj2;obcMdMP&j4{_5_7M?32q^*d{O8}*Hc z57s}vN_h|CLA&>)gTT-ze~C@6e+EE4wzcqOG;H!b90y#uRW;ziTKq7ZQH1(|S2^vcPV)|HR1Y+D=)3(K(bh68k`^8DtD+Vfj4 zDm7?V@cJR^(pfUCiGnN+G*djGV@upvMDsEu$3UpqBaBUBA*hlF7@0Z^m#5t#BsXOr zBMMV&ht*LYm$(r57LEXQRy+E*xAYO4kSkrs5JA!7?P>k9ixb8IcjAMvy#0~lQx zHW1N^!JSAETRy4j;8h;;X!vKiMH!fR*GhNsqF{@@vZ5If5hjaBNpC?;xz%5YF?8RE$Cmr?W+Q54`3~&<*dK0%9lNvs(F1kb5q5| zaYq;z#T$h6Dk&cj-f(f;k%utFjWzukCC07M?Ss_{KOG)n+-wMO4s%n&aOmr8XYVoV z?UWD!tCfd45AHl#-<#9M6K%uhHnib$-H~t!oZjMT^l2@9vaz$f`QZMX zmLvi3k|$OSEm>|u=#47&p%c$&YG>o##@g=2oTivz1p}u^azab`6TLvzgAVc+AX&@_ z4vyjIB0W}^=M#`%2T4>jQE#tRGUyM0cdb>WvY5Zi^B}k65z{TM} zb&XD&!lsU-=GaI;RhHYsCT_jMW>Ei?3`a8%Q_K~PZnly^U4MYZyRI!F?X1hZ*lpFFs?d1qd0Cygf6KGb_PcEVgA&P`f~L&R74>3|9qgPQ!}MfYjPr|1&3GnW0jcvTH`;}V zb{x-v&%psqK?ctD8_N){%Xp?}%;i9P{Zk}0h8-@$%^YB!4JeTzw?oAaDokbBP2?M3 z3W)>(q3@UK_nrH95se9e5rJBENB2=Ybbu@bDT=juYvHUvIDTEY{Q$5cTF9n^?Zg0E zi9B0c!eGzB(~>`x=4H;Lg8esjJ?ONWcz21DssN(3meqOwR%*g|C{48_Nn)t^P)C5h zkD7h#k|p_>H>TJHE^!u^GfF0%%avP0e+bz*6(Pqy$VOO^qJ(MmW2_qyh$(5bNrDs=31&C=)Gs~-6TvcQ4TocML=&XPV}Wh$lUvbocj zlWtmCY;~?Z4yXalVK9;!P`P7JXLdhc+u69YxdUv^C%2r}+_5~0&zQc8$5puL;^|_t z9bel}ULOSRnQR(x14je4DF~A}sKXwIMP>#DAJ)KA;xcmmC6=GHuCu7tJtpkWFbX=* z_x)71*c^DaN+Hg}6I;adA(~WpU6>lkd8m?N4)UeE^HXwlnS6LXqpEy+I#c(#-$h*- zjR{K6Ha&w0>Vz)Yk2)U)0m(#k+3mTq+ZRrrcgNPw#GUWd#p3uCm&@+%y{w6=w~)rE z2~jrBdb0%6)oFJGH-3W643Z1QXV0V3*M`tD)Eg>5+6pt5(CWO*jiFp+b3M|XtSB|l zpUfS|{3oMEeuTO0_qyY3=;em;5fU)rs8tsWJahQzlvDh1#hU=1kK=LYbZH;CA6wuT z$pEKXPS}vECNzJ#b@6455e~jU*J)MI!x`l9QtAfNWNN_NFsa8H6V#k7I4iE&9^ zE|I6s5Xq`4D(U%F1BrCRZ6TH(nMw`-6KzqZ;B2D1gQB;7lE!Jz;MkX*#KA$@FHOvu zwp0DiHJpn?vf;zFlgJ|7gT*zWkz^6d&QZNDC^LKI5mOz4HFJfq!#p;|zlw&Qb6c#( z1BBrsmWJ|oq(089ivlUR+}yle%kDqe+hFR3#Q_B&t4hC2 zNuE$J>6@>3^OZ+^SV{+>@d?xm7tSXbd>uKd2g@71rZ~BU<{18yAvR-QQa~_qU1z$T z+a!cB>6~ z;+B)x{UgoolHP;eSc;%e&;YVkA`U5DrN_1)v~-%Yg)X4`~2 zchTGWWV{p27C6#`oP|&8O(tSzjNA&^|&^Vzz{*~}J!40kp_I)T;fR}GA0|1weCCzt%zM}Hd zs}r1|0FCTrDev@Ydx>l0l?Gl{89+(kK~xMEor*r<9^0Qc9-ON+XmrpAKSqNK%u&Dj zs`U5(m*nF7qHKu4$`>8+FO zi};A{vlURYYC@E5s<(4g6(jEW!oHgV+xs^gpJQmwfzE<@{W5g0)oC8Xaf!RUD3#bd zwFq&njWk^GpEmhiAg?g}8&E*A2JXGU#g-D@1pWLVUyfoqsKZkb==GNnOa788kEZvA zuLV_1k>MCB@)1~1y0e0A1jOdA1@n+kB~D#_>I`SBgYDsbKW<|_d-@$=+!H%vpXH?( z5;kk6Weg!&_gdm(*sX~Hny#}y`1QBV!#j+)@aoJH#4yr_4dZgGMQqy$ze zz@|))2Y*DRAl-onx{~;bsYvM%mg736w3x<`6ct``o1LSXSv^Ar>_KCRS`md^x=0Yj zXtOS5>MXOEsM{dSX!zumik(ffD-(`nlwxwuK@U+Ec2dI^d00L^DKhzLHYplcT#$M! zHg%fi1773CtfcZpT zY);B-ZIJ;hZ8AiSCzF!X1}51#t5EWh#)H>sq&Ba@=A(gu?|}h`Uu%&WcjL$_BTx1x zetv8OPugOfCeC77^hOpz2y>2n+&Hlqg=uBY)cY9(qd;{DEn8h!^<0kE@ zgS@%`8S3oPZM%d^pAM-DiqtGPZ*NXlb`spy^#lp8R0!)NH)*+09TbTXCji|`2}9sy(1!p){R4#{zG854XQK4rYG z4C}8bCKj6!Vmf0+#g2Vkvw22&OHA}Q0WWlw*4BkTV3 z1Y6C+pLVeCBEg$23n$wX}nvB(m4>}SuEmwKHG$YEmKX09Py6}Tvp zXW6*#4LXyIRP<)JS|AGnj~CI#V(kFc8Vmr&^f0_Rx2#j$%f)nTHQ^|(QZCefC>&&x z+>Xhma~S5ig`&XgK}M9tr9iDd7hgwWqk&V*!NLf;%dpq; zfMop0PNX0Wfs4#ND@0HbTl}tw>P%+@ZGp1zkTyh-ksTV^UQC<>Wu}D zPCyvYOr*wkv;T?F1??R+_Maj2$){rmhEJNOBW{nzF`6&6ojT-lN)t=jQhsuZt?miJ zKU(t#=t&Ppm1c^e$&Emh;hjF-P%UdiKLD`RTetsC?I!+rYvntE&V|YK=k2R0zAMe6 zK9YM2OFY2!iM-wy{tQ^WdQGGU9t;;4QR<@!buT)MyXx6xZO*QqP61z!Mm7y~;~$hrlsvb^xoU zUSWuG-7_+Pz#+q3gkNs7z*?b#zci4@KsRDmmXSMVSvQmm&EC%ak1*0tkaa+W`@gxd z{fOQMxbUbI;hI_$xQ5v@iC_U>L3YdIG&pUJEk>fyq71kQ?jvVO$8Sss>dV>cq5;6H z%yK!gDPJpVU)tb4#$iB0NaRzIjPZs~7tv%U0x_Of05dk7Y+-3$RQWu^M3}~DvE@+O zrGv7CC*MP)`MJ>(%OXu2Q+VJ^5f({JY>VW;{XqwD;*GAFO@Lx4E{J$WtRv5Pu)c|1 zvfM1(bcwBZdLRU4k=Y`EFx55;q3YNS;f+KJcV;=m*gaoMdQ_wK;~a)7Hl@Eu1C`36 zuB+X2cAFLyK8I_2qaH#&yH(@b9^o>16fKBmk&$#j<Df3)?Fm;$aF0?6(8zrVfqmgj&= zUrG+R5+Ke0HkRnEko=8y`~CpQ-`*Q)^0#%kkRgMPhFNv}T83K^ZZXg9yB8_n^nk*} zT?uc(T?v+_4FNHpEEiiU`!yj`E}4W?K{{OfM!Oy*m;Z*Ofs|^(Xda#%jfS1B|2o1+ zxNc|PfAVbIC1kN9yWAd+T?qz9HM4+mC4ua@=9Oc}OD&ie4Xr&3fk}#JkSR>k^v}~o zgm{dn!@A_~4u`cJm(yp*A#f5ZJRCaB5zmgNo;m8Pp4u*yt|g25pTdgq%pEt|5dOtz2O#5jYY4l5kU;X zE0qf3)cT7Pv$Ri}n8jhL!mmv&F6nrSfC$>B%0TVmksO_A!>hleIf(4{+`0(sXsLzH zmWU@Qg%zqxEtbjHI6JfUMKN_JX(jCI*=rjaHy4O z$8w(O&(|#@)3?_x8YR9wPw~ooP&j1jU12xGU?yGv7MV zX_7M$#a~N3oRj9(2Tk+aX}{ZTwn)ihFd3_6E99k-cxeZ1c|OOeB!hdtdHi ziQ-IgOcl<}oS!*cqyB};T{(7a=hX61XDHWDa<$SWO*BdcUxV(#6QX(PC5vOF zi7`^_)L}PPSp7uB87HO^jDg&P|5;CD*KB(N3ouYGq!KCE77zp@?H>p>JQ!KaHZU#E z@D*4yn>3F$jv(z2Oo?#Q{%P^%Js1;9;I(iubl-m(`U~@^&R=Lar>Wq?Pn4PX!ROGm{ohFx+UN{ED-PRGPT`0V9Mm zH8@;4!z8OY3jon>yI0k6*RuCBxR~K=*58kB;eHq7Ww-H(t+FORrfsv!(gpi1=5ifu zvYfh}9;%aSs;5WKa`{#o?Yk(b))-i2v;t)MX}ACE1XnuRAPeW=9o<;~vw}msYW(LT z-d-e71f4i3J8cMQa1adwp438Gi>@@e3f!Q`Ju@3}76od;O191XZxZxOBXz`5U?7GV z`7a<+N4-{IUXxKEZ%}uSJp=>h=y0Z}`PBGNHE`iLXkbrTW0{-t+Mh08$Nz3tEN?kf zw3=QXWTol}+$(evmYTCzIv?;*JkGSyN4XvdlR@jQtl|8YN7#`$DW;e(mUC)uojw&o%eoYi` z$#x_SvU2kzTth4h!WtmKC2$$yMGxUytdK)3EL8$unR4!0_*~iq8IS*FMH??g2*>M3 zOqPp5_cB2-(Bh~E z4XAnzm$@VPV9)Mq#_Xi>&vIGe~{VL2Kgd{{|Nw5Z?i z=}!eeE)Z`^CPZ|mAEGc8Igw{$pGi?T6tKS2&X$@h!_jJNfx?9f8-&X&0At9!Es3#B z-c&N6bW1r+@fL~64IAZF{VishvR~(keZ_8*RGc`RN;Iq_EJw@X{|CWvF+16MET2|a zVzmk);7i#t;0=%%0vz1N)qUXh22QJo2ysA1Qb_F9WXQ3Xg<69!I;@daQLpj2Fzl(g z#EG}AQ~Tu$@@vjpQnoy$_KKa0V5F-ci0KnKu^OjQs!p9gmM|Py(8w#jQpMgD6?&a7 z?n&!m-yW2%8xnJj@D(vTu)?_4#FQSWPb?4M-K7hWsjCG2DZ4wu z=_1OnKt>^+SFl-$3Jw{}O6I|1Lctz01xW{G7BMYg4}9T6R|etFSBmX!r{{2E)elx97(Z2cr>SaCEID7 z;5wvUhQQ@QkFD8406XcT3`9s`C0l>^2z!`h#3t5HD|61sL#3{K^Zc@fHm^Q?_q+A) z{>jyHRUtd<14w;y8@?*kIR?XM70Rs=?aRW6^o;RDN+lX=unlA2>RgcT+?JlX^fcWg zEL;&~PGa)IXvY=}slwO+eGG3iOT9tm?y%}kogh( z*baYDr`8#R0S2HkXULpGqYq(AK2z8 z?$Epz^zy;J?$8o`es;ul!`)G2&P11fL@IjFW*e<4Y4`f|+uAT+^JCp)$zol;+(*6R z(0M*l^lGD1RA^UOOToo4uzpK-xqB^i8hd={aP6r5wADGpk-DmFDYS#QECKl50a&|! zl-w!Y3lOg1@X^2>98et)$B(N38fO#jEks&AJ`r_^U#ut|kbM4pbsA=ctFJV86gckL z>c);1`&wcd=m(?SYw;2g@Z5a$ap)O#4pNZ+Oq4B#DT!>A|1chuF`TPlQ?TVR{&H3R zO+=P+yjcKMKFPmWj3%AzFAZ<9T(MeL<5yFoG%Z5hkp^1ee2d|_I>Ckwebt5_x#w!Y zeVZ=MNY+6FSI)+W`oM17(jmvH6m3kTJ4{P*HyX7T3=&PS+y&jpD8}_0ZQ~-IOQID* zNi9sijex0`XXQjz@Z5`Kj+(H$Kx<$bF!u$aNLyhcnUjpq3Mou9suk)v5Vc^2R#^)~ z=^Jog$?ka5dfFON(3R10CGX`*_CWJpc|o2Nmflc=+EBbLPYSld6dt7@$7&_p#lPfI zq*nzaQW4QKT3&f9c3Fcai-qwEwtSNB%0PFW04ueesq6kww!>IF6L!Wr-j_3)D>L2^ zlBqRPpd3)8YweRaxH*%0>uSO%5`*Dt7*r!agDT8hX%9&;GIA4n1S6ibB0rM7Sc0=I z2iy_$;LZamOKsJOcwL??8R!pST|z{8{{)7JMzdY3sY;HOCKuaGU~JU7!$LH9xhlGN zT#8|Z;u@h@s~nf=h3gyrnnzXv6Nb3M&2C~XGwC+i$5<8(x>dtdRaYgWWT3-B%My*goFaLZbvZ_g+>(80T?zxm?T^27RW>jGf_X-$6erXdc!nh$t~;7 z6{0!I*8m(CYAc7p5XQiNCXHp%%hlw2abFnTaBpIavT)zy%znKMpWmM>(l3_#MfFK} ztvOue#`i%huS3?>$?{~1F_LCrRfcQFD)^(sa(C3Vge5Wr6xr-ErZ9%TWmOvAR{3DX zt_d?THEo|OV#QhLYvsRbAEJdkgT60^5FY0C8opT{F!>bgq~MQ`e-8sTHLm zN56tai2v!N)o7iVJwP6GpXkrevbV>rAiBbtTOS;tLMyRaw0zC0IW#VIvk;O#P+^ks zIh_ljM3Bo0W%;^Wp2-2wLINzdz;}jE*@~N#7YlCMlnsj&0d9}=t4yMO#qKb*mZsHj zNSoKx24dQ@!HTGf@{|v6b?uaD(e9Td~ldXkM_FKn)A4*X`>2fsfC&6*kr&D z2g!fbfd7F~h}sNX;Y{%FB3-DE19ds`y9lJ8R9?lXpvD%KfHXl`4x6vYQ;U7CpcF5f zNEoz@flomv2Nu-`EZMcO6%;$+q@^WNBxNb`zAI2Z$L9chgRU}NR_E(QP-M9y49Pq^ z9o{r7!}}CR^k1&xnT+BBgNQLD;6(<~piRTiU%NW>1KfnG`YsafD9O=nZh9^REa-*Y z#+Z~n$DTv_7ba)w^jke&o}zhG6XvLv#nlQG3Dx?!V^vp@Xd6q|roEk2B*Gvf80AnBqahoA>+z(bCWml>iZ=w{G|)chSUk}X zhu~n11F;1nqXFEY&Is9!W5`L2p$(a-&7q?R@4-uh{x+oCveDymNHREcPM_UQyryYsfR@46DWvYsgh9EeMS`M63QesY87dDY zb`kyJdOH!AS2--la%I^&o5Bp`t4=ZBImG5&Z*jpUf%`^56DPusE@=N!t^knH`79z+qOXbo?4uczdXZ0^upwL^jg_qX!JL12i&SFjEEM&z{;1>NrR zwTn0+s$1~-SOG$`?K6w#%uz+e&6#2aqzpaiM#bLLX`+UDhZRq@UG=VEO$bIWZ5z`D zSCh3eX*(8rD_qe_Cp=PV6(KdUc}QutJYWtAf6)o5+pFFgc2WmeBQ&F)78N*hxL3D# zWy!KnXSwq5hZ}XhBe8-l>iLXer156U_GH2I5p7|m)w<^fFi`Ojp2R3MqLwIDc3RrR zw@L6We>=qpna^)y7CQ2U8pecb_LyE@g4)i``u*0`JlZ6Lp9uYl7KPx%qkhY%(&b@H`Hgw%8ND7D+y}APSS@VqzyqY zs{V(2y&%JoaSxUv$%A^Vk3-6U9fAT(eptw z_D1)}J8IhB;0?*u%H0OME8>67pD~lD8Kz-GVzh05EiPlTce|npV{Ku?+fQ+U8SpPWW=RiFL`AF@c3(Qn&niXe*pD+@BILiC9;|4fhVc{+Y~x z0#^e_93e6H>d~P` zOURu70ytr|^U@@ccW%Q?2se(z64IcqJ+Y1rX-iMSO`RNt;XeG3a;(8k*g=6^RVazaqKt{0bs!!R z0E9Le`{eoc3m=|i+ zq&Ys7qKK&vql#76ZJg}4#A^#2O^O=lLXEd8xc?US0uO44Tvn`L&HSkJT0D;9rs+x^Xo5yq1mT(h}7Y7}QMQ&tuI+hAkgGAGP7*QqbND?{+ zPK#&M(#Cq)eiFGCfn&bFkSy?>4+@(uK9C+kk^|y0(ube62QYOAK8VI&rAaXKS^L6D z`~Zt|K&!=~MKoC6%n!w4GCF+gp9v!sC6LcCbP7(S4X#(^-`Tw>121-n^~Zx&#_eY; zH@h>o6^y3|YwJj()owl1vxTCcWC*`3Mcj~0S!DdZeqVAMk~rAaWL?Wn(u9e{^qN$i zFto;C${klm6V3%}BZ*0q{n%DXf;Q zvLUk8_D{&XsEhblISwXSp#_L@DA=S!qny`UDlH!ew60U1@4+b(+I! z^;B8tDeN~msCbI7NFaVnCUunQNOmA;T1U{W?z*ifKSd3^D15 z%79>$P<0lO2bRt@Q5XYd0;Suq9>Y-uq?G;~l`-^da@;GgUL%uAyTF4&6<3CfEBntca5>NcymGV`Ww&sn!)^X|^X9fhj=&<)3pYa4vNe?X4&PyJG3%JtXn98ml94tF ztKqO$ugGDeiUVlWJOm(T%j%SvW$Z2jsZmyCH}U5O8;>zcr(y&Tgc4n;ut1sPvQ54Zb*EsAmel= z`(9ye^#-#W$My>qg+|L|vn5=p>3lJ}qJ&&7Wb+<-@kpYMSud>ID>?WJ_QnC2iXCIk z;b{`0CanZkEbd(-z^ET!e=#X6ZBvitl6=zS%Q~fRGB*a}Xq=GFymyS~?lo0?WwvNz z*LqwL-P59aoL(kc!{rJPI7)<|?*qdZfnjzs8DGC0!^$b=hc!3o!*U?^Z4#d3b|=U7 zt9XElvC;CN$Ac6C7tv#=C%g@b!bQ&7c?qQ?Ze6*E$hGCWVJJaYOp3k_#X(_engJnI z2UV9UP$bILh5n=k!NQkA0guvJfGPCulBiG)*L*x7o4s9f^+@yg**s+$Aw<30Mkk=KWNqUo# z&%}9`Q$4WSwxN~VO)s(ncuGC!EQOgj8lr88Q>^c>iKnqxwjPU2FXwEr*_}ND5l#%1 zFKj2A%uL!xA|RtLW*0E#=3|~P$0D~&RyI!GXh&AN;;z1^ij_iC4DF=F9R=~lbdvCd5irG_ddP~i$|)~zoeSsG z3CKTj+~iU{v5(+lXcB?CkV`rW>jC8sJ3YaQ))7|3~ZZ#zsS-x9l;vZDyiN8YDq)e>3Y#w%8kI> zvJ|PSWI8hcJ8PO7U#-ws8emgM0Zk1OA~1x<2-=^!QsH=~4m>Kelj0%`8G4(YM&kZ3 z5?5BW-37Z8wk++I(o;Nz?}~zq0PlfT%az7ISd2U@UxR4D@woM%JRIcB8Q{v8elei>MVwt{{`FtWUiP1%-av9`t3<8R4Qw)fw3V2Obi0A4{x( zz=65WqmHqQ7(%AhvQ7F0fdiMg2G0@zLZ6X>QR$C%IUM&hq9S9LO&Z8pFcwszPQ#T0 zTY^|4!B;(g!Tpf(oZ3P`lkmBO)uvF;))+~zFTo>)T7{yjf#8rN{h?M5OP&2jYk4)o z(Af+FUDRn}G2o(QEEuV<7!NG>M%bH<2{edzW`f|HYLKZ~Sg|b@F|F4y3rvm}nIyNk z<)~J^lNgn48WqBsH4iqU@z3&U=n<81E|$y%bc13J3z+XXY>5zpS4(rc!yQ3Kuehaj z)x*S3Qh~}Xq(To5ZV`jSo;dO|-vQ`rPotn@3=hp&M*x5i7~fvaZWg;y2#cBoLua%o z;$e8?^ohj+R1<8e*3i_^F4dcB0k#NYHGn5FL1yitn?1_Yrv}shF}x)a&1)3I;MZzS zEsg=kCcKg57k)(xcCiLKTF|}tz(3M{yXAQ&CR&}ntpA-wqh5x8XHnb)tc$`r1vCRm z9Y1coraM3aVWu#>6I|yq@}NS|T&TE@51>~ywZ4qLJYLT9c(rlQ391woupqgUhKBq><6+#zs-ba8?Q-cyE}9&F(Zb8Uq%#_=hX zZAf|+Cq)2rFl}n5&w!cJr&UxGI4WiyPpD9oZvSn}?lQCSnPfenH_JpN zJ5$WzCfM(`PXt5GecA=s2PW)JIRS|XS4A;W(Zfblyb05Y2==u)13S$vYB?E%WaE~Q z@}7?@DR<2Uv`A1HG9SN1k9i5!3@kYbS?#J0HK-DkV@gW6A?|Hz<4Qar%Q5kj40*)B zwnJ3UROQq0E;kt1!Hi)q`=cf7i&`v!+4@c7em` zdear+u`JN9T3m~(zvK}wAL@$MqcMP(A=d*V$cc<(EKGR}RzMEBnnIMbE?l{=eVmX= zJFc=amac&s{h+;8)e=;#E@R2T0vx#vDVL@vNvb(!H7m#CAY0$lwxj}F<`?y$*Wj(= zHjto{&}0ef%OtkiM{P=EwJ%%iol&D#GCv>F2-Jg@u6m4fVH8SnD`;8dpw41r#7KZp z*uD28Tiur^bFodAy5gkDR!BLT9KKciEK4OhN$Doau{{Yjph@Ak3`JpQxvuy7KvjjF zZ3n2iF5%Q3^t+;KBTPopwQ?BKv(p<$+zG2%BgqFqb$-oK;G`|;m;psk1S0)p0yi*U z+38`Xhq#Fuc|sINJEt5TxQ9;%2n@|QsOuxC`z!J0Xas0Y|A?&x8;ELUG{EgtS*3T7 zL;L@cw202pxi2Rsc6u!u6lK3?r4%uFU#-B!lr@d!x8 zdq~OVXh3Hns>OTUG&GC@UHnuYYRV4STeD~V5steAN)Q`mC5uZh!G6#_?F-t1Q1YTU zEZ8x~h(zU~)H%WtUzK}J;h1gdzKWYMbi33;b-3|4Xh{&B+Ou*`CU&HV@Awo>m^n+l zFniYafPF;ZWJC`fJR47#+s6PL}i0px;>y{TPK`?wUARG?VIS~G#S(rLy+2jIl8$I)CvS1(o(lWjE+)-6(6yy>BzELiU!gKKbzV4tb#b)$=T z*#nT$Xz5SPXTkYR_#jUlY9fEh&l;zd;s%`s937BMLJZ!c62-Ee(sI1Z=+`8s0YPV^ zTt-Xq9@yR?lFckjD;o3akjb5=O+K5cgiB+Ip@g_0T`N05isUVIXS9jIM#f&0>6*`E z{->~FC^p#h)bs``YUW8I>+?`~r`PO`K-RQswEAbgG%`aXAZ!UrNJ=11liE6xDzjlV ztczNJNM<5lbc=BDMd`g`$#O+kS7ic&>5@@s2XbC>)^eUJ<(Py!kuCU#U^ojrYOg8u1iI>N>VDO0^FV^;o|DPY zws@g1A^7o%*4(>+p?;#tx{|ED zuuEeNxgH?EalkdyyJ1{oZP32UGud``9S-D5!stz1MVoo@GVU6{mY9+%Kvx!ioZ|qR z39`#-E@61lDA(OSb08p+RSvvpR&Kmx=(hA3>;l z1c6-<9t2jKa8R5*KISP&D8KTB%4P(>VNJH9DV|oIT+R?v4-F|Q%oSM)Vfbg#d5D(+ zDo{=8g~bH!Ld`B^^FCOC(Q?(9r^6K>VZd%&kA27Bg<2_@u`iSQp*}TPdyI2tbQ0D) zRIvmbM>R19hy}5$VC(yO(sKmj3;uE&=F7x{@?c9Pmq;hObH*v1S0yd+FF+tkb!_4hGV8P| z^eAIkr;-*Y(d4n^B2ed(4@Rl_I4|(MH%2W9R2h#DXE~1#_hHbigM35H9-@qsDfT{x znh*l0Pg$QYsj|NcE(hB*N>Ag8j6G$;SR0ZI32j*xs`1FwKz*#>LxCO^mNeVbA{1>}r^m;KRB7SLcrg~$yi99;?PerVg69W= zIc6W!H~Mc}&Xp7qw-!nd1Dl{_>6bBgNzLQCWIGKS3 zAVk7R%E{4wgICQaNN6RxkJv7_UuQY$*c^sAI96nk!>?J+I@X*<#uETUYw61pw4pka zs9EN7B5Z=5L|QLP+yZYlwapyHgm^C_q8O}BZp(xAaDwwys=~|hG7T<;qCe~$U^@sg zM-L*|v25h219?bjphA#@%96YQBS4Vk!gka#3x&nGkOmgnE&!6$Ec-(&xp@ zkswslxD&U=$Qce>U};bTc1esyjQ5qb95N$EDt8LyUa73md&*giVv_oOoVJp3$tKF} zruH`sWDye`!s2*&PmH2~wNTWQ)2E0#B=RifZl0tf_dYR;uDxKI-GC2?G5H8ENxsY3 zME-Y$E?IiztEJbK?@%0gUedva1iMO;rO|hrWgL8`G7Rv{70GhxdW=NDH`CQm@0JfJ z+7YzJl+elJABKqSnKz#$%|PSou0v1Qc3}m|gj3g;8}1ky1XU&=&`{BW&3+}EQdDA& z03C6@Fg)y!x|mSi0R>T~1Kf>vnzV2U}~n*7R%s zmM9MG)%w;Qy!v%}_46N}{pDA_vh}V!{04%lbgw2_f4gN>?r!a%$~Vg4Z}xU?tA)3} z;W>lt>A}`1F$l2+jC-(GgROsnSHG2<@U|EKXzS;A@%197v3LJ;>!0J@SLL1UQ0&cr zyY(;e=J%)h&8^h`v3=z&6#E_7@!}j_$g!pGx39jny}<&%70AA6-QWKBt?j?dSAU>; zA(492nd7N(gYoy?+WwDN@S79%M^@xNerx-`W|2$Mj10ED`ETCZ{(t!98vy}ZclQ4O zduw~=*YN(gOEwdGz4vR|&-wbd605eodhu)9|0iCJNHB5U*zkE?hvp@JbE)M=(f7W7zIIj-Qad+@v{A+r5aC}%plA6o7k#QZNr0H$K zH^0Z*guj#FUd`;|1_T|-OauG8@s#N z-3L3_TJ~^lXK!=;(Y>{u?BS!GhYxl)YMGcifF0`37+VI9;4T8@B_1*oUHkkgrqixh zl&rJx+q5CkTQE&Z^zqy|L!*suA2M33FX9w&t4qevcWjfe$H4@?XNjTD&dzFwy-}?{ zI9$fubKdji_Z1tX#%v9jYQpD+;Ft_igxCf4vX9_3=p1M7oxq@jFCT#ZFb%wx>wOTo z-c|-x0a5w=UbWfvxEgWw;b?QnO@`{2>e`bPcE+TKQeo?GiD>~ntI4B{M%-8jG#yLbk9$yN?t(2WP-hf9X40k7m* z8#Yj^eCT%PRJR zFgXwsZB&Sn?=vf<{mAn!wrAKAuJU#}I0AYHr`-{xvLb8}3!zc&07v!|Tpsly2F%0W zX@1ivX>P%!vmI=BI}A6$t7JT*Ga#NvresNqr1w=K^q3Hnw_&WTKIg;dD8{DiqzNVr zZIua<|pitIq58%hh+J`l1h^oX=j*{4A^EIi46XXQ%H!q=*sf)a`tFv6TD3pFdoTShCy30QGy7D{bnDFXVlXi zW|9s2+33WZXOE!8vdtRwQj8(>Kx9cQU&>*d>Wa1c{ANryD+mW#5WfwByUQ@soNCpp zW~jJ&Ba^Q=dcyAq!&CpJ-MgBmawfKh2%#r!rU`VCQqi6t*CVYI=`T=*-#>6UOodPv z+sKUzN?RsKC z9x}yKkx9xYty>-GHzVG9u!hB;gfl$X|fj~q-w z_9&n?9))+hWUao6zlezbo{a{|;Gj_;nu(YwoCFUNQ^3XE+V)U2dbG(tQkI%|>T1cWG4!j7d^lk6RJIs9o(1^+O z*lTnlK1NiqWc|Bdi3Ny#KnKm7@ccj+0lr0j>P>Q`PTd+v%xvS^&db>Yp7T)ADa(Xw z0c_SP&xdYevsLHyW~+}Y*DJX5RpB`XtFc=;Vbu3@qy=04l!o|)k!K(_yw)%Ah0_jR z`B$Agsb(rk{S4RlBKIt0124|R9fc7S_g?_e>q62Z0*7JjwYZ}powps7|SS%6uDb0{cZra;xKlCbPU?2w&xJNuXr zq|O*-tv*yIG6VFA*LMPV8~O54onW-09tMyx9_G;2akdaa5Z<;X6~~nT$h=}^a=X=t zppY~ijmFUv&v{*+0t)rpzz9^|k+LLZX;AeZ+(1M9CzK2dGFOPqaaK=^Ut%Xht4AGN8B>7)Ll*{T$W)4+oeI)849w$F3^f3PIBVF% zSwn$c;y;#xO3f2a4r-cs3h%>+Qtg!$EUzL`oGuHEpa<%9mH9HL zRshjB?XoibF_*A^kM{z&_~1DeWFGB`3QIqYEgx_l;Si=d$x|ZLL3`vZ?H*1U!L{11 zT8X4@7|Y7;&cp2r3l8X}tK@^z6a882OPuswkMv9SkCyQ*=^6Wv-W4;3vv(SO#{>}A zay`W&Jnb)CX)zGF69$zJF&gN)%zkYLzeU^CKr7)xaS&Nr?r7jST#jKJJan+c!ibkt zD6%m==0{$sq)cRVoCEG`Fygv}2>8aqS(AIZu3pKn`j7xQ!#WwASmCbk8F7%d!F%j+ zTXRCCV+Sb&L1vRr(6h4<94`F|_i!$Qwn1x5DQzFS$@b+qNVTFx!q(N%kp0{hziEQ4 zS}!b5IHB-kn}xUyfRHqbOjO+&RGE}|vnVqn_B!Y@LIa7a^yTnf5a=&}KyC9tqQ(_g zs#{xHJv&z!=+#(guti3u$l9!{d`fg?0Z36=hnGf7Fx6zuW2#N7lX?*n>3|E8M+l)c zR4WjuR403|DIDX@9!9C0_VtLfuqLV&ogt)a0==jj5TqjrHyP1S_=Pv9LR?2fH@&K< z0IUpvWSM7Ofwj<36^wd;KRPO3>{ux-=Nv5Sz|_&YqlW28!{t%}x=Od6L-oVKJ;-d` za*Ehauh8_;BG;L5D9ChUsa8M&E513w0&l*xKivASG{jKPZK3 zjr;KC$7lG$f|6&|vCxyRHC$HJ1NV@;^Hu@|<}S9iRO`GXV*vcSFJy!jFq=2R5B1xn zOLf^X)TtF;y+?if4#Ww$(mHk$+?~=QEH8FWPr@@?zA8~5aAUMv)q|etWw2;(;MzV$ zO8)sl@6RF4G!hRXjT#Mz%?2zB&v3bh<|WT-ZUiSdfmT20S**u(MoK3d9|RrHOv5aE zLPT($;SL1}Ch0bC1c$}4_p;=EH5OLJ8Kh3BIFq92{dci!RzgSW8vk{CL%__$0jy&7 z;Fr+RtoiUh`0%K z5SOc7qusg+4=UQx*>1Or&S=^!i46+jvw}_euzKs}&Fp$oV>y{r=|&j@CrtqmM4ZS{ zxnu~hdb#A;#L{d}I#9wPboNE~CMApzG{TFMdWGgo+~*_3NC3=?$D%M4HJ)(+Ae3O( z7>*c8kRK)_(Q7{$G&l*k+}?`DK?j4-T2z}0>v4B)ZST=;{lQiwE)K0==d+MM7T^qk zHOMu8CD*-#K82dPFmTz;t?_qtBk718tCcttw0*{nH5oAm-jUuf>P=^6Lui5TiTO~F zEDlc`M;J4N-;@WF6usyuP8$@$2>p~ov5)fnGRHi-UHeY$rrN+8u;reG{5Ei$B31pV z#F}HKVBy9r(Z_9!;4R@hj{Paokck-*)!w4^wBJiRpNJM5)3hYG*ejY(E!t$?{g)yVf!5l-h zU9vIJxlnmXrW0*29IG*skdOpU2K5LGQ>V_El`qm=d_(GVeU#VbQ8Id%Iju?iKG#^H zrqmv8eN^APkHvQHUU8v;H2PuJ3;%k~J8B>Un7$?(o*`~Nj60VJ7czQVtA|cujufdP z+zD%nk4lxjuC5an;76s))#{bj@|D&#EUv5IOVzQylO+kB#g%MJSGLY%Q2~GT%FEzR z8lpX%pxCYBq{CjZCyGtwAyUu5%|THIqr`B@{9F=ygKi-$Bhp9Z$9a@Z?8+E2VWp^X zkK+MO3Pl9tolK_HbAy8y;8wHxv%jW7+P0V9-nxd+&A&BK_X$L4WtXrUZT_JN$<`x}!%3g@tbpKSdQK!0yyK?_a2Aw?9uWSN&c z{G+XZ8<56}l`#ABtz#7XmNb|`lSwk9PPTd|^Nn&D!{;&IN~r8Kv?XqK)_6*RDf1Zd zl~S|EP>M`IRGv@mq`aLqQYEHso)-Aw2$5}kE`4< zj>53)u}TMrlROn$KH)Igt?zwL50fFrvtZQ7vNhgn(K$Rq(l$E;i)bYtM=QtBUK}!G zm;!uB^fO-^GAkbpe2vk=zV(l1J0jt0Y;XMSQN4TEG(#odczTK`$Cg822w$Tc4vSDU zKnh*LU#JxJi#F|hqO(>jW^91@Lbyib#4g5~R8;d8p(uJ@R`OsAXZq?PGNmk?;5Ixc z#ESUvh$c}=LbHC{!`(D#V`va=^;Lv7z{CpJb(q?_tvVul@Q|nDL{)@mzW1ccK-3!= zG-2`&CJ705glQ*<0YVX2duZy0yIv1NN+6$rrY=Q}f{c4nm5{Y>*>6M0hMpTu&ZdN5 zTAY%lao<5P!UUII2JHbVF`Wb2_ocjX(3Tr_Aodz0v-2Ird?pli(4m-wZq9whYjdF2x{Ixj<0Ds0vpJP8zV#g`~E$qt&%Z zM7$7(sr6|m5BkHNxFmATgECLp8Y%Yhf+PUx@KUw-Oyx(lZU3VQl1~Rsp*D zW$Y#3=u3PtB4)fOuwwSFDt1M<*_-k9t5+Gx$=Ifzho=iRt8vZO9&SF|aO~3OyL)$V ztT%4&F$DEf5NF#U@i!c}_Dd2f)a`QK++yGLVYkscvCD&LZ3@swV zs2;%T7;15Wr{l!-HRma?Mb9N2u;A-e12i5OM-&#c0dR=?wB76+@a!{tF!I|aS8l6aN8&*uaifmcB+-mpHNFuWpqS~KiIH>Sy(W(Nu zMw^aRwzXMo&p}w3LgmmbYhrkeNLU58qw8W7d6CML$+9TWB{Tsnk0OOcYUC=QK3QA| zY%rE_r;Hp+PIP%uuVd$uHx~7|qcQ}6YHFFTWR_rK-JU&mK^o+M|C&(H>zUgLj0|&;;R0cTNFZ)Me%2L z(Pp=ggPaE~)97ZR8VP3AzJf`ewN}Yuc&OmXD*n5X1s%|Q$DmH=l?!XGBvgS`P)4z* ztg91AHO+u1Zl1z%J%1Ts-p$6)q3h2=#HBxm!_S?qf{7RkZ z26|wttR95vv_XsnRM403IGq;gOQxTc>lf&(00LP)kv=KuM+CwE46T?kptlUOK&Azl z2;P+&KZGi18tK8}2)IhoF;%~k5Oy9qgyjYT$rpfY2Hi%sE~W!)DrwQ!koaJ*Nj9lq zo8e-f-cq^P8Ds)ng|{7`>;l7@i6bVHiXiO=yE>B?^zr$X;;t(f0?IM*MQRL? zIpIcjjC^pLx|kJ0q4Aj0NmbP15LHf6h1fYJ+cs3L01%8D@~>DiKVDwU?fqMt2DU2520C}pxibCq8^}(zHeXFUVH7e*KMy|(0!=Qt?v!< zn3rWPt||02ncj_rde7vqZ-`nuJEM!U8k1`3)6j}P@_$DSoOT0CK!%)b%U&7HcERtu z!g~~(qzSy*swAn!HCX9(1Ge78p@!CIUBtLlS%1Y;a{XDN{EW~RAVF(0(6)EpHk8u7 z6nZXbtBcF2B?3Wss#r(%h2N|jek#u>3)V>+9L*$ zDKMp-7cSGUav)VoM!}*J5-YIfK6b{AyErcoMnZkCb4Y(!9r|)nt=e^G_jF_B6@0|? zn0vsx4QNB4m@V6-a``x97yXdT6!^Z)f;;0NYhs*4|{ zv>dzLK(NkedCZ?(2UiY?SH%qZy$15Ln&nT@$M6K(bO(F1;Rc`U(aa>AIT&6`cjHO^ z|Ez9?Oey_R{y*g!UMAkp6|f`;x0sNStT_&QC`9-FnIpt``x( zFmoLQG_#-YN5ObkW{qIZMeX0B*Muusi>sK`X4I8NxT?5l`HCB}v5PgoP(IQwwUocv zjX-t~gj?7A3`48%B$gU~lLnKf^^6J*o3@(;(Vex_T zxZXsI(JaqjY>dqumnLFsid^5g;lpM|EX?8lZe_+g(K?n$;B))c55tdKv(FHDThrB# zhI3Y|vJl!*`Py{`G}P2`IOi1pZ{ZjDTOWtaf@b21nRx5Q^t~g4wm%ay?V5ugU#+<1 z1Hvv``#wb;FT7F^)!{tNz)xnCX;CcgtnRLDtPWnVAzGfxABaQVvS?i#>y>LHiNjKU zW1E!i*);!?2}roaE`YGRGjAu|iaD{4!@~}Q3{B*Mt~Q`q0$y;0uBzU2U#H-?Fo9!+ z8x!3bzcx8~u2?$C<@qD>Tn6_5Bw1ah@_9h9*|se*Pe8W;7Uondb|^SiV)~Tj{$8%( z!kSNihsWz&ibRGe129Dn(Fx&)yLE`6a+xh~`NDg*-~0OF;C-xVXrec{DPv=D%MACa zu2Cz2w{FL8(3poN6qZj8%S!V>Y!gY8V5quuV?$9*)4}_X-kpE@CwsecEMow-9A2~T zrhnSin`Zrfz777QhEt_&@HP%;-C~nMu-t@~MUz-;g?Zic6Wh4}(`_tEZU}a>C#*x% zBv^wCoyx+Om$R`w@77XDZo^c!p6?*|a~zKcaw zI}iucnxI%Q5{l>HdJP#C9VB@#s{R#OL>>!`#dU|Nn5Ey-AcB`!I13md zis#T0#nt&@Gu(ozCtO#JCM#Cj=sLkaesD|$QS9`mh7H@U&ZLFfr$0S!Q^V9xU&}NH zP>N1ivEz%K?qefVKix{~RsD5{+~PW#VEGAe;K>72!*<#LO4%~bS2}-a|7hPYp-io7 z@(7Po9H}&R9@~!P+wHCn$Y6!U658~tNjcGxRKWvsIQ}MgQL*W&u0E}axfogft^aFI zpxm=#e2;DJBwY3s!vzm1Oa^)WFFSq_tp|28Oe;1>+s&q4xV(O z!9~o+E}w*)@HqrC%^r*d@uq=Y{a1jCJtd!A<@-=6ed?ge=`m+|r&BJBVsfe|G%snR zsv36s77j?-aAkG~s%0`va%3yA(iw)1L7T^Ao49M(A(4O{Tc_Bw!Rs@_NdV|?;7u!b zZZO{qPv+M2CL>?+BsuA4joOTOh7N7qB1?~`emu-YhC26SiD)aT?KUeI%p0h`R~K;$c4816 z)Cdwh6U1Sb{2>FJjh!dM>j$qPD~K!(1b_L?0tbS>SR!cS`PDmb^8A-IWB2{MQukEy zSMMxR;ty9P;uP^)_Tp#jH5HBi=ABQe^0T$UI^O*0JO4FrexZx}c>A~R{5{_Oe0m!r zjhBD_&hPW`b-mPPE3Pvg3#z+(bE&ce`trYcZh3g_ER{@@@_v@Te9rGY{qie%GEpk( za1HACEFHN75tXi-TmBtY`nA(Ka$GO}YLxv_Q#LU3kC*?X+W7-cq0#!obITv<>6aS1 zjhDZBZuw(g+7a+}X6;~gLnij5+pj&GohWLjkRM=eo9~?bx7R%+;_H{J3_DO zYQWELfYND>&(qcIAOB>etE(>v{ZQu$KiuCZ2iR{uf3Cm3gYha~4w{Z@%PJt<*{lPv zxC=0?Bptwxv()=!R?=lGGBo&c>qwcM4qGd8HrE?%ab}YQb7q(*fhehv9dno)cogQ1 znSkQd8JREBR~c>dcdkC2DEVA^uuF=wtq}M%HaCYT#alo<-NAU8O84D#HFJa2dNsn7 z9xwBs)T|!VAuj|L#go{`9Fi03J43{bZ!%E`8k}{H&){92Thcz`Rov4oPNg&Nt89Rr zfzd7SWFcEW*dn_tf-VB>w~tq+PdBF*2dRckIUQOQoF znq}QG;6|Nj;!w@1gde_)n3vR*(s2~;odY_2@|~>%03PmqXLnV9*Z6&nFZ3(dZ0^@E zpyBxWv2;#9xbkB9SL8+veP2VhR13Cf~A*HwvtC^HmuW7JViMcsQd{70TozQb0=>j%dx z>s-5ir07tAZ<>B;#RksEjTTSD%fZ%@@01)&sjlX(f#Bc=fxxN%WDxwlji5UTpBV^i z1uHPxTr6Mb8_cG!i}J5q3K}Jyxk@)K_%%af7}X33Jm07=fvp{r+FD()Fa{i@?Z(9epzR}49y&uGV*h$X}eKc?J^OW|v4F9l`C#aBwQF0sVxk=MMjsuG5^ zHvHz5j(IfzjrPn(n-0Dv6hP~KZc`Cmw#7hAit0)~MMnMPC+ffgRdvFEGtKDCsKS4J zgC0I#8&*a;HBQR+Ex1u$%3+PMSH))Pyy`U5QLHh7i-?}CE@(JExFe}@e-m>y2798m zBs(T&OkAiUG+6xF!B{p{4unXvI2tDF zRfb_~C5;!k?fV!mG{Ww)cl^SvVZkz+(VjYZI$go+r9F4ZcOUECKDVi?ADf0(B#7vz zY$vHM`Ad;CWEK}3-o)zqj#w~{U#uP-9ZsW}w#xeEd~}%5{AfN3b|)n&CZ?X(LK>;D z?ewETYm$TwxA2RTs0l}pG9&{~-HgTe1y+l=o7!~An+hh0YemQp)QG&}BsA8o_7P;S zq^2V}39y3rPE#OXPb$cJ*pAU?U^OWx$*wvY?rx_c(aPhH)-$HMEDSABZn52M72KSn z9rhp>2iIf=>LlCg(l!3RoT~H^#}j-Y$!2RBgf|rEG_8$$I#d1`-)$qDkAn_Lo8Zn< zTCB=x=~cyoNXqrBJWyJ5Qs#+|_u8h(JVr<)IY%ctKHBFd52ff0p||QZFtf<%v!kc-(nr@L?j_sVf2llG7d>YO zmvqqxx|Lk{PhU>ep1m;u6GG`-NH65FiBJrv_(1gM(tuRZ*WSF8|3O6@T>JVvBoA3V z)TO-)J}-d@X^?eq2pyv3aIKvyK&^0*+n0zJ?2kL+aCGi&;}U%n`k>V(gy~xJs=G=j z3JnrKKD)W(Nt8rDS)nKI5i%?)^84M)jFsYBRNzy-C7O0Ll-*V^76zc3aS=W?iM`s> zkwjs}Z;nL^t})oCziJ~hf=vP-n2he89^yvb_((;^nvlKy5#pzTlHmOI`u_84Eto7= zi(cv~=>q!OlilNa%|s2b&Gjs#Movs*wC162NkLB!;{Z0zrKYn~eA8K}wtuKz)eTs{ zBmdLR+oZp1!Z0_bXFgmv9!*F#yG0@#@b+jUGli9y8l1H7{(kse!c=|sZ z*h$kO!g5oQq@28|2+I}_P_SDVL_)V>`N*TrexfNE+N2FXb_vZ*Q@l&FtrAZ8IN2`e zUN76}R1p^RN{)4-S=z82V`qQ=U`3)Tl);@g{MeY_QIF{?8-wi$Q!xxN3l$_B=NUPi=^VvC`=R3%yJQ9@E}ra zuO19-vme-)rqliPE%-^e_XUd#n-VE(kp_%$5gw0YxDRv`Luo@~7xh?9_&-4#TT_K$ z`dC-FSL1N-6{2T=%@cch9$Cl38E=|=awSpNkb;0g7lUt*1Ztx`N1f=TBZLvB;U6}=17t;ma2unzS~GPN_ty3be?Bb@n!+CHCAt#@NHmXA1V z?+amu(qyqrnNFS1uqUwM++5kSzH2UkR=_IGBhE76b$hO$scO{&r6$7#Ypn-m4$GMz z>ypyyV`Y-ahg<{AXI#XOA#Or?8(o$fc*g0B@9hokhBa;kUhmvAjTq$ zVTQ4M1l|g*?phQ$Knu-oo?Ml@M3do-fJU{JGk@VG4(m8YX+PZODq$G(bA`AK-mu9b z`HN>7%$Egk5;xXa`_rC09To}}d`?w5YaWU*CY3I6@!SrIk|K8(+iFkO<CASlioSQ+p37}P zolSRF;jHX+h_9$YHc&Y{a#Kl;T|3tG=%+21Z!r{g7or!`g9b37UY)k#;zjJ-R|_dw z@Q#$s|L2UBj#%_>3x-V0NUepFa~QmCgVi1&Xxj=D(7w4@;iwkZ|pk1aE6?Sfw`@_ zFVksHxwIr)?Bm^SeI*0KWOM7qlHYkeMi;V>7p+^&B{HtqJUDS7tVgH3PO>_;e*&*d zZ`!x4aR=or_HTVl%bSI5UiaNq?5>_LMoE<|rxOajHJEfVCr#|{)iEA;A`J=UtWEncj`#N*qlHH7 zx6zLsDOBs4Xo+;Rq5LBD$Uzv4=65b;=BGxyIb|d25Je^f>@`-1^>dWSAb{frle~MJ z#QUP-mITrq_{%a00(EhakUX5R?Mg}r0JJFLA>c2rJ)c7cVs6!j=6pvW!I=gT14D9 zr3>Cq`*pQ zy%jr_m}iPm9@-054dU4|nGG~)ZP)6)U9{d9f=@cVQb^uBC$(+{gxh3YUqUWpoI&L8c*( z>S76!PH|b~A+hlrlPL^A&f>}8v+hd2K~b$qO3TwA%@_65G|BaY!Tc)0UQam%617Dd z+#51cWS(@VqgC#Lb^<|b+~%>oa)?#M(9bXT&+*jVcMz~$rNW!Z(RyYR2|%%x$bZY! zOa}tv!C=I9o#2txL=XU`Wi|^h3KunMHcs6ngcVZ&rdj-N(VfsHQN+SKGWxuAAdw$( z-QvIIS20R5=NW9#MtS=H(i+a+wSS4w2;3K>C604o{9lobK3T+cC<-LR+toENdGr)n zb$WEM-2`xJyFk0Y!hy@pqv^>1oMpZzXj0j)#O{}`ONU6k704CVplep7Uk9@k z)5c~^#uJz|l8&EcH*R85L$%rK=9nT;*d)cq&nRi~@VTsu-$LIs0cHnVsE91JAWLUQ zV91jvQb0Tvf-HxE#an2d`4Gk&W!mMU^0MTZttfBF30W{RY3XqS!=|*GFAZ!`eDOrJ zvQ9;8@sN_K)kSh1X0AKSD^6&f-XyAyQYWPs0G8&QsKMiwax2xy1P-MnlhE39RLW#< zXsc~UOI`hTnn{abl-|$vA)@e;0`2U8J+k%mmV%5AkzqHu$#KQbHBL&0~C*3+i(WH>@`HDIZ&BG zNmhfsIalE}H z-fcMS#GX)Nb5WGCqw{|wZu8^{Ya5Enf)wvoyUlRz=x}pd#dxMp>Etc<{-PUkODEPe zuFp7pDbY^c0{P!Jh=k~>O#+G!c8*VI^%@rppC>ekE47R};hT1?`#Be3;i%WGya)@B zFnpuaIDBC=e6~rfD2#b`y0Je^VFDUh#via>yYlASR#`7jz)lA_K*jab)0exk3%ZDg zv|E8sxC|M{ms*Pozz_AwZeNl=*>VbG- zlq(g@{jiT6nm6pkzVTC#seit@vu!PPSc9s-Lb0NmlyKRqmKKFBeSDy-j_#TcT#k&f za`JO-^CEj)MuP)=I*BDDB5RHy?Gj>uK%%>JrHva|4mhB_wabkfqTR&-WtZPEJja%A zm!b|IYURT?*zgSuec6OUkMt$2!L+ZLNRXjT3lNRU=OjU3y#x<1n5qzhTYjtvLu8VH zU>ry`LB{N`7evq((6d?matq*+sz2!pu)7$`Zcd)HnGO^&)4BeuFmd6bwi{@s5Xd&k z)L<4>C{ucJCVYFBs`D~^%>|e!!)<<`7K!pP(a(=Fr#fzD^Z9ik8ChR~fet_dEt%^Y zc*>@em~Ax@11P%TJaZhX*MW)k6|qeJW>>W_XLi72yP|aKG)zl1JZw~+I^yQ?Suk&^ zyAb5&uwK-=9f^`%uUaWt{r+td_l+U@1yvvtGQSkA6I2 zzY%=jKgovS$0pI>HW^}@m3Z`GMaK;-q$Pa`TE{jkLq#dqvAzmjLrSnh!^ebNvVx>(Vsh+aan+S@;3+O_xb4H zy_%CO9;$jNL(BzQp*4_V56%y6y+B39yWmhu;vzoJ%A8Nn<}uw4=AWVL4i-?g7X;4- z*KTgz_z?9yit0Kw2-BPt*AA`@*nHktymoPMaAokun{Quz3&Dh~AHQ$G*R>)@oYw_O zRsCyT{|&4E*3~!P?5$42Z@d+vNX(^!53zN9JO19Z&1d$nolTlofNVl<7)KhFw`rF3 zCNexCICsjf>x1#HX2fFNiE0&WBg^#~~=S77rJlnA%F zqD_15Xqe`xmJ8K57botZ@=7q>Dd@nauK6=k7PH9C?sHbC`JT|4@ZMxB1X@$tn= zKz4E9m<*;`w~+Rl`)Muq@IZ)sV2?YCtOTDnD^^L6Z2Wz^Gk646H1XP%{q4{zI8SL$ zy4zQ3OCzrWO%ttsRz^@YlK^OM*i(ED)0!dzvqjk~(lWT^nN?HGCwPgOs-?hSUM`3F ztheN1P_=3>Y3z%Gn<-8hk}`$Ofkbi^hqNEaj3q$kcDP5tqo6kZkyzDa*k+=)&5*T# z{cAyEdcM(AmZ>FkVYRR+?Ks!R#u9L2yp_UJ+0-*0050y=hDygTe^cQBm@{?wPK3ye9ApO|=;6bf}`q45gN* zutYbEsm*#ZbjH*tR99m-`L%lNdz)4mFVokI)2eR>EF=Wq6{Gy- z^04X==X3>a79LLB$8z^I{{=a*dnGJ~WEYGw`Z-lLJRjUy1mh5Bm@G;Jq2%picFbYi z94pNbRWqTl8aQ5h_g5Ab2<#gA(rmVv&4^-1$pA=Nv|Y0+rw2HA$EKA(ww6-AAswfN zKdz312}WvXi(~FaTgb*_>B|0Bzw#AnS{O65oybvGK%O-f=K3N_sXPgWJfD&*K%+~5 z+S{#IJ!$R0XFPHO*}54GS~vb>YZk$IsX$R+RW*GQn!U{ab|Jw^dGwIUe>GLr?LywzFQrwMjT?wk>oWb`IQ&Nd#Qr3`77*czy-5L0W7&4%k+<%F

aFO=jnI`jFG5J2;e;j=``XFZ=8p+#At(a7kKG-pcHZ;RO9su(M z#D2ygPjK-Nc5sR#CYgYJX_)kLH`!&=Nor$7N>HthihZUm$(j8rht%2Z!gugV`3&py zOGW_4U!tul+~Gu)t*$G_l~!hOzla1@yCR)@Fk}^E_;s2J2dS=_(z2XX_c*m2p=ot8 zc1uND1R@@*r%~HV-UJMT%UV(?%s2E=J8i3xutygJYAj6Mj7vn%^~s*hY@nxlpW{-6 zH(EEkg_G1}Gmt7w^tdizmk&YvoL2Gb8Y8Y(`SFyDIZdrurnjL(P>+F1tj!xS53t@yA6f8%C}7UpA8b*OzIY3 zPl_}$1XZ_4m<||CL>Z>K!D`$w-&FG9pKw5V=}7EQn=xKX9-0lqvPxf|cb zZRb5SBdd8#n%Ak);L_5-QY2iuR;*SfOF_>tE9h)TPA$dK^8^O5Tg29m=MSp(v!5xc z2l5JG7m=W-cmvacNAhAMGoR|FQz~cxn)G!dd9Yz2m~3*|!OYnHIHw~TNK2VrM^*2O zgBvA#krg)tRkW9&TO7OtoVFAsUU;#v=r86m_=2lC27w&wdl)Rq6D4zYPJ0J7x zr#Zy4dKiyZ?o4>}#gcg?o!}C8}C0B_TdzM=HXHpPHJpEVh{A(2dgCs{#K8Seu zXYc$)Z#!i|i0A+MoqvnxKWk>WI0YGR{_Q*efqJz!e)2G0{D*h`MtL4GU!vqcyz`HE^atD~63>2r z`JX$-L$K}P)Bbq*SI&{^*_ur{LcI9(bIVus;^#YoPVxHMx#h3w^_LnQGF~p8TfV24 zzi`(z#%^}$N9UG5()&MB-bc(#G(eW+$DIbGTdl0b`)_&{=I{Q&XdrSulet;RnZNsU z7RA!-^yr#E5pWe28uAf_;G?kkkH_t6U(c7Q4%F*9SJp4Ih`rZD%b#8gv`b%%y z{&vnS?^%EObv?rUbIS+TpS_L#w&LN>cg**JmBVw(e@=CNrQM9WaQ%gI%YRkH{@6^h z7QnxDZu!6HZ?3`2e|c{CZ>reOwao>{e?H#+p{!E`uz&m9^8co4EJ)YP;`#q^ZuuYS zITb=9h!?+qZuy_+1xr4O%<<+6uPy)7Yu=QLn(_RnUt9heJ^!WLcahMd$QNH*{u3(l zi?cgQlo-6We2Eg4@HBCdz)y;KH6(oG$%NYter90%31zUXULoE)WmO z`n3n$h3OAF?8Y9>Qj9@lStynWd_9Sz2`&CW3{jR4vJqStVd*8AL{WF*v zOOtND3oEyuz*3mFJ!!Xw)P_g)MR(1vVkOen6F+1eh_bW%(aL1zt6#@GS=LFt{zpy|TS0{(x8-4UozD4eJ>>HB*5A7(bLxxL5v5*2-h^;5nr{?&h8P$GQ5IhVB2JeEd4YMTu z#$bXQ9j87K+>!(a*HRbJ9$Nn)ZH$PB0BjN-TQVMmXtE}fysOmgA9)!d0R?uW;NU5V zqJT*u7Uk%jTZrc931kdDy#44K_uhXrxc=Vn4!Gs-!S(kZ{qAp=*d?_U|&CVf=n7LmdL^ghOYXH8rDP zLg>lu(#EQ8@N&V@!t;Z801SB&bFrKgToLs2=;&Z^Vd44n=i?`P$K(COCkxEI=6$;G zTbhAL3oi30J|*QsN0y9VlKSrI>a;^H5qfDS#^k|{Do=Ly*V6ZIaVMl__{QG&6usjB zgWG^n?W7X>Ie$6s+DHkK-bEVns72y|?a5JkmmJG77`_j+iZ<`+?3$ekvr7vgsWqmP zgFHg_)->{wL7cBhI^MN-${$=^u+i2=nX!}RX>jdci5V?Ii}fwGJ@g)=r-&Xsy|sp` z6BL(XPH9b?ibK)%_w+^zqZAMb+WO-u(R=pKwyoX$y)E6g7n8uWFZ+{jF`!9>Zcq1Z z%e3g3wj8$f23zvp%dInQi^-3d<}i9zqNSC|bba-J<0)T!aPQuumHXEpeFLf-E?|mY zpk>n;7r0^11Dc~_pT!et2}!?CjpPg@-cuJEE= zsnktV!ga_zshb~o#X+h#7S+2Mq^lpQ$;i5>K$PgIsvtc)^hw!Gq%JFt3p0<|OWZ)x zsCuapsd@w5>Gh1GIfrDEAO{oHWji|LA%u7ln(!u!!LWRM08%HXVY$Nb z`&QT%^^YIBhF;rwllOrb*loOgty3eRn$dbTKLuX}UVXNFkG19!YK$z%1I{i^%vcyD zc3zGL*D-2&UL=d~=P(Clb|#zJxsUdb$u=Ly$&-pdGc`t}c+4OT(XodOMYtECzGwhA*S{Qjw1iJVYDCX*HIa3hP)UHZz`u8^q! z|1;md_O&?#mMLjouU`A=_zM5KTG@pW{mf;#$)P6PagwoYr)0gule*?z;|z)bCe^C` zDConA?;Y>1O(GWkVAW(sm*Qhxj|Sc1;2Xd=xP4zXr73aY>rV|+i`jPd zZU;iPhWV==DM$45rsTn>;Zg3uYQGcNDj?Z+^0EIJ#joq{uH1g_)*~3M?epV@_io%- zdHCqTt?SE9pW4J5q&Suh!I!TF^AKgtQ2lhg#`KIv!avl=1a%_9rsI^gT=ml@%w8&Q zL(ubBAaT81VS;++TZ+C#&H2dK?T6e}IN5b{xPiM)f8ZJl`lxu`bvp{@kIiPi2M<-z zS(~IkFB^&fcD(z%TMVJ~P!1Z{qSRV6lQ&`GF;PZ(tkwIxvX065_B{HIB0iTo=U@*W zA#7RW#-(Tp88sQ#4P*rhdZY+6hxAI?aD)S_vQ|A={e=LIw;*0f#yuJ=NE<*3$3HAu zl}KkbqiN_^BJirUA!An(h#NEsHh&<6NdXe;O3JQGVIfBIc$Wj0IHMscHgdyzbm(mh z+>~(Mo+RpZh0}-FBx8{{T2c`0uFpFN%Hr)7=cS>NDufx{1>3R4a4pkA)wUD-_SAyh zntnP-U+8FiO5DqQG^{nUZTTU6?hSZRWYeP(9(d!qqrh0x*UXrS7;rUsq?1+B_?vgdFuk&QP!?LLLPOpQ6%L~U&+5V&d0!4cJ=aHK9{k8^ z5h21}7>*4G+za`?;nh)%0!&??KW5P(1gN-YLG`_HJod+X9L?As<$)k7sm0(P6-tss z`zLQLzaLUu+`A4jI@Q$NmV~}2bPWO zjk}h!OGv@VGpy6uJ#cJK4)?fzx{l2wpB5>PM2K^PXI!Y0g7%*6t%rYE!}70reLI-^ zOWxRZ8kFQ3r6mk)?XPr&4;uFu+TWJmy7Kmw9`M`?C+;7O>A3pJF$u#`j;8%*yPGQ- zwiT#$;Y5;x%%l|K=V1>slab?8?~}$e-CxA^<>H-eNFJS}eL!RkVPf6MuDhlwwW5z7 z&7(98HCm{@&RyC5$ilM;^R3Tz#k@#-e{;E9qWIR{w=4vnqqi7$QfvHmk&R=5+HM4@ zzRF&p{PrGAsM3{_P#$ERY^--&J@XxsOv>`|vLj;El9!M8LZu?WGCwVHNWxg-Teq#x ze4kPlrGm+wt^?lDrsT9&H7QZBqDmx3%OL8H;1ExaE$yosmB6Fylp1xsCuNk5n`H!5 zaPAsmb3V!}7GgIKt}m+@TH(rbeN#iC$^?2}Gqxla2k)7vt5!nTM^rd2M{6o{vu@~g z25!1DHa8FINs?D`A6Hei(5jFH{UqRU9Z?;FlT%~ZA_YVj+G;6sb3z2NF-9bv5U2Cu zE)Beu@M3Y=!gvSS##Su`Wxy$_b(6(r(9 zMl2sJi^$)<_3mvMyJyHwz+?thmYc9`O|f=&Wl7H{sF@ZQHF(bKdVetPBRbGh68%fA zWC-XS0_@4L@;iARDxu$Y)ZDrnN_Wawh&v>CQza|V!+ z+EaUKSH7sem8E(vop8e$`tjcW%J#Eela6L^g|Tsgmq|reC;D{3^yvZE;p#fu?vkps zz2yzF#q-Gxefy2C%uRQ9m-hE6^z`&CGyCd}y52a%NpQHdzPU9%*xccA%PUvsFiw&9 z_2}i&RM!n^9~Mu2Ld7N{$u~)A-Fxr^F}FK z^EIA6EH$5@s7jKyW;nMFIZl?2_ol0xlQ~MSuO4pjlLP=oq6PAbJ?Ex`qi%C9 zhehY5Qm!+5K2bGKmuy1jq_pkt?YtCegCb2m z|Cv~q;ruK;5+aW|_vT8oETl z+>YAfff;HctB&Qi;7#Rdq!eAk(%CknB7HmNd;4y~{ouVDW^N>BSJORfQzB=k5&Brl zX5mG@*mRUTo*&4NTw3T^cWrw%XH?I9BIv{ zch8@`bJm6g**s%6-|}rJ-v}5j^SbV1P|Z!f$|_k@;%0`q0|^^4{%LjT6{6$$gY~Vs zt&OGTAp!YkYsP_Bw{vUg*=-|a8Qwcwx;lsX@Q~h@^jD@t^z|!+orwhcK0`s3iqF{@ z6P)bh&B+GaAPY>|MHQpD^i|vk#Z9 zyht}ht95;5SDl{zkos-Atr4Hc>~dEfBwZO^&Y#ss}t2ezxZ#?GCC3r2YW5Tj$G1E6KE6>euQEz?EP+q{adnYXJWA*WVT4-!<|uuEJ^W`S)@MAM zQ2cbCbB(aLuZ5d48k!RF!b6R45KicPbM<7*!wMt~tg7M1S)x)p5Goa)I}@5-`ZoT` zKp(JGm169pa30PL?o3{;?X$VuR#w5o;{%epo$7Ay8@g}i(sd`DF@0wEkc61sj)-WM z26Iyw9l7GvBBJKZr*SDEx-^%UMYY;!sUnBhWrGzGim>LF95)0}zPyC`#>Y7I>&zq^G*4$YW#n2--P3T8Xiv#I0}F zD++fV62p4&6&oGiP%-J(3g`oKsH>PI^C??=KaPm7Py!nPPa0?#I4ew78S7HWi&?|9 z+UMLzX;Oh=HD%uRs&4MKFfDJlYo&~4>rOQeSrp0oI&k?Q+w+q!WMjpQR<-H1DyCr# zc!4mbVre8*OW+|jQLv$)SI8TBa2z~Bx33Y9?WsihFhx5X$qTod+sz2gD9$8ikXVYQ zT!^hMy*6c1Ly&DyPJ#@JQMiR^)&^l~EmbA3=_nuwKk(wgrbA7HoO_7rr_ogGtEyL9NK7z=^C1S~00utz5n zCWg_37k&=1p+1>rJMD&n_PNn7w2&=fQcMc#HFRW)+IJEM`-ElD{@5GUuv4BH}f(%gHKEU0Iz;pPr z4p#7>G4rWdyk)vK?|K@PMq=&ya2Alj7Sf2v2i$VDHUYPou?-M<#6N)rgq`U5WM{_> zb%`1=jMdFrbcLp06?7TS0^-wb2jaYjo{$$Kj*b|ovM4a*=*G{?Do4ygP6VPTOl1S$ zneJjSFE&%*)Wv+Kz+o22&W>+RL_&i!(5K5xEsHtd2O6%R@lin*$sCi79GSAA#Y@hTxAU)|7I^D%$v))gVq-Tuy}#ion~<+l{d zbqrv#F^chNq8IEvrVtyJyoB6xP?<_cy7Jc2<`rU|8>}F(T9VsnJ(5@=&CLz26*&Y{ zmRhotrSzDck$Qwt8tm58DtSsQTRjy#!tRWyt%s42sPtFB(Cf2^xUC?gT9q(!BN!@{ zc3dxh-+y8i3d+yS0yY=zi{t4A`{eF!HU;%f%DlLy+1+cZu!F{BR^NH^NpO%v z194x!*TF`M|C27GvKJ^W(KMd!8Fm`i3N7%cJ9u~a;Ol1O7qw<%MLD~&wG-iaU7@Pu`mMaxF&T8B#fW0Qq9=mOf);GM((p{qAMg(U z(N1T)2DZgM6O;RNA2Fz5Z-UVLwuUwH2^2mnlQt209uJ^tvBqK+y&6o=G~F8E01GUI zD<=Z#tXz0h4*GYZ!GD$Z9!r4i`vFIhpKa}P_m4pizbaBZS(6nCT} zS{zIpy5{fk&>DPsybG@)&%k)YF3rmi&C#+j{J1RRYAf;UPSjL~nY3|mR=@`$2Lr<+ z9mRZhtFfkq!tu6e;pJ7bh+}!+s_6YEJGzTXb_lZ*gvryk6sn~SzGI@-An8qGwAN23 zrqyLY;dkATW~xVF zO-Zd8z2p6mrfx&C2Pv^c^YGxsWJMgM^qTEhYZykzaf<|)gH>x>Xjp|TYfo=J+cQ%7 zhMIqxH)hE|+MHr|S(~6ziE%7tX42;cWL%Q2%1%YUCkWz#P#?;2;8W)uz3dV79w@5XHwhSGr@q$taZB9KSic0Cz>4BA7 z42_+4tWIyCV{53%yi{Ql$`4buiV1wy*ljndyj0`H6omrzxgxsX_Wg}fWhOxw#PW*7@Qv)jDo{VGr zPXLxkl|}a>kccg}I+ia(NAAiKc}XIuq}rQ}2iL_A?-64qZLOG1CiAbVk`#I^R4x0m z3aSF|V!z|2dKM1v|A(Y&EBJVpJ{ewr@A{2<@7=tPjPk38I=o}~9wW|^fC%(!uesT%-IUkyv1{;Yqu zF0HLk4vsipldU5?u9mq$I3xNz4{AvhuF)VWkA{h9Bv>TtXSGge)?8N&-$~aeF}s7= zS&sWUz@}W3%R11UW2F52$82`3G(0wQ6i?5+W!y3UIw`$Ys@aSC^zt*$K~J}>IiR%s z!e;)#8D#urDYNlY3`k=)pSzK3Z)BO4Bk;oa2o3=DOM z&zCtK6m!!xRwHCVb~R#Zb44}GQ)I6sbSD#F`psK~XqaV4!jQOij+X09 zzbp;b@2q}PH`NjHCCi#})0D}hFxf%eT4Awc{ex9iw<2Al{P5!C?&AdT{L$L{rP{tL zs%nA=(AN69R7s$ULtL1hGcfgT*my-!udawqk@c7|%ZY0m5VU`MkXs21r8=+h#t0gH z&Om6^7Y2Jarqp->D2$DAOnP&sHQ7YT7-9OKlx&Hk?bD=b&%T*ex79S6EbLT5Av;3i zI9&0LEib{dKyQVW5TX1*?xsUN)9zt!BTg^URUth1* z(kG|+7;ypnD}k2&9*`S6s6fR4(Slp$9btV4z~SX4#YowIqvP{4_Bw<)=ld^7WQdc) za!R-cC`X805)w%p4D_US+oobS85U_ubKnm18%p}@N7*rY!>^iAgfXl%QHEt<38oR| z%e;g}O$<-P5=@@Y#Y*QYmLKbY0_8iVu8jN0O09!1h_}8!0;GN*a$2B)x+Kd@uEMy7 z^Y@0fPJkl!bOHcX%IAB`p8;LQ8|j-f$ZT$KY&j9la7tDezBUJtMej|l6jdrK#O%%~ z0OwUmche&xYdXlWaJfLv_s3~1rqKD_CkiTBdbLR97^G5O3pBF9RLf>}^@m6jJ{ zoAQhs-TQ`O&bvR-p@AbZi?9~HK#Om zQevB?N>H!tzGZpzj90697OE46s^WgpxpvIyC}991U_RrQ3Jnq1n&DTRSJpgjejh|0 zBjY-q={Fyu<&J9mDD1#yAW=T*9PtE^7dBMZP|ZE;a0Us7od|v5<_xloft020!}W-L zK3s1*2n0q7f(lDsY}UeE=Aan`izjaJ5PY9u-M6irzUC`jGmoJj7zGy|7#l=tb{5}d z{O#B~Eml;)%Ii+T4?Y1M%r;hc1(UeZ-OeoI4APaH;?$y8k1pug;f-fwyz^o?&lYlr zZ_M1zovB>SM+8W5K4KS2C)l1p-Nzqj(LLofT0&?Kr~eVn_UzgQNitD!Kyt3QJZI+9 zlZV)sGo_HGERR)G*WY7w?Gh!ZW4RQmDqiC@;})K%nG4^A+s1H zLj*R1^>UPVcEifmUAVxL_heo)P>ahwyORyxp-TR*aH>D&B!|%}F)Ca~B3Y9wEuk=H z%aVnw*rR#(re z;GhxNlK3ebV7&&cqPA!DtrBT@wlEios3OT^$uVn-8g%OQjW+@{guNe4h)Xpvk8+Vn zAh48A$t7UM?6D7m*sxcHk0jK69wKwr5E*#V)bx{dbA}zQN%oN{DwIuYC7R<$Zw8F5-{5juQ1 z;=qEbPBX_EF7`K7onuu~gN9X;yrrx2INoRr@%4ePGXH!^j;{QFx&6`F{9KY^$QB~U=LnD9n?&BJzF4f z`dpj-TdxI;ulil%r>C8Eq+U-hSF&psAvJBJef+GTuP4*DvCG84P7sEB!WRn_w{mxC zsTz61N((GMel7c?P=gG!mY9B67*l~%^a5V<8>7$s>$FgVO6l$?Ut`;llu&Y-B}c%_ zlCz##XXRkYN%N9PmLZ+R)?;k0U1z}(KDX;kU*R!&6~z(KbG&BMwv=N;zds_B;34Ng zOSK}4(``$IEK>_*WvjM6{Vil;(^;D6T?nbif5z59SeDC7q-Fi%vnN)@ZMMovD4k6m zJnJoLd=^wc$(xhPbv;G1Mz`9Pm!#Q~Jr-y25~Xb}4K%@0kls(Y-SQ`Thh|yqXY>kv z{~n>v*ref~aaeA0JZZjS>?+iFf~vKd&||KnGE=YEoD`U75tm)J&JVo9RFl}}wy~}3 zbF1u+%_`f70;hQ0vWU^jATk|uE977L>aU&qfcWaX(D&C3I{Kao3zhzR6bblylw~4e-M1h(0Gn6w!-$oE!|FU&SUbOm&anXTFL} zF^)!!gX_nf$vqr#Ysi4iTZ)z&eEo2BeQSI0o4Xtg=gaSKl?Kzm)e^hE1%3B@KGgJl zxWA7R{WqUK*Wb2MzQ_$jO}hJytKQswW;FQaRe$bWRnuqGg$``AE7Yn z%Ei0()Z4ORZhFK7AzO&yTLHNW?At$Fkt(5D8R0LP<0GhUqOs?vM~9qOOTWNd`ntZ) zHJIx<=)sA&HIfhbC2fYt1WxlJw@dZeB;i1QQ+EXjH7aaKRkM!k>fNgT8~NliV_T zjfUrkZHiIDiu=fICos&g99Rpxx}uZJK9d&*t9!aPHqH@Y-ZsNNxFmo9Sz_-H{$UFe zI@pEk}7jCn3K35Y=%PBV1u)k`ZVutd+C6$4U?lV z8!P^Pq*f}53CGT@bQ5LAtD}Y+(!SuxGCEJGl0@GebLJfA>(dLIOrZxOxBl#Zc_t&v zR|~g?$n-<)V~%Q%sb{1FEAzt++Rr0Y-UexJRSJT%2~8+a4H1L*Rr4ZoCg@Q#G`jG~ z1y%MF1Q+J&AD{YWeb+@6>WG?ZgBY>tV|}@NHCoaGYm+Bcq`oN0+tJXX#XuWF ztOlgHSLs!cB5N>3{*ukD7ni;I)Kbj$|v0SD$1y9rVllE+S% zYrGi}2<|aHj=KcsQDO4(@{E5+`gQTLdlv+x`EBi>%a(Ogj7}=)*FCD!`tUH*>=Ugy zrn?q?JsGp}j;gCDg%Tgr=Hq~8@ng>WR1tN0tZkajl|%BnFB$oS#2&V<8ttoF4c9o1 z=&bEKJZ|@HNx&JA(%7OwIn;}k8aoN_vfS_m+I6r6mx`wrQ6EO;ur8+4nKG_{p6pEy zSM3g6sM~XZDG?VJ7wZ0L^Aqgt6Xn0d52bb7<&|w!2_}bup@hd#%SZhg$o9o9rN_!CV=>gb+Hwh$K<)Z?@q~E zwTjp%Wss1fMHgOlY%6({R>^gwE1Efs7H2Wi4vD}E5YS*FA_iz%><17uWe{HoMmRod zes8SpFClxbFoLxHy}2=eM#JcQKJ{4C7g61N_a5DP7@%GvKQ{N7!*wCD^~r{A{vou< zvSpW4saMBJgp9lx_$%AlU=;a~Jla^&Spw)9*$J7y370nbeiMnLJeYJYp^8jA{gEe|vt1&%O10apjR)_vTk9YyG~A`Cu|C!v;gWg%POGE+ZRnHH>X9AR z(}}^HDN_Mmwk4zWr>voQ!vT#(*s7`wZYk*6Hdb7%gyHx-Qa;RrW(iH91A#f6FS|6I zKxil)m!J?X+?fvMB@}Rpyqw?&*a{7feu%;i5DZjFG-{C5fjsd#+<=e)CQ0d_Mq;dgtkcj*!S{l(s zT7X&H@-q9)Bqpt$~-3o0n7VQY;R_P9IGl}r&NEg|*@ z0}3hcvhH;{SUMpvO10U%3>L6LhQ&Nj*4{?e>Z;u%1XDk&Nd+Z@@FSWHtOB8+S5rFT zPGXl+FKTKh{M2qZVLMfV$lTXleS@!NFM5o*Nmz7F`TADmn6SokX77%?tyYN8L(xzO z)sp9e%~PPaBeSenNFeV`UbmF#YUptz%Bi%xO&mFRuA#&3k;+&@c2JUlRvmbPzlaZI zu0w`clijf1iJY3Q$xq7lqtmBIzVjD25&V2|0cOfQcy=W%e90M$r_+PO3Z$aY2poC? ze8uV}#Y-)BWhsK+ZsVRJ*ZyjGou^n;rRik#x)x$u2_D|qk>iC`R#_ZV>*+6L zv`UOMCbQ(&+dv&v_7&=nE@2bqto1r>KQ6?n#Glj*Rvb`my{92ALd#vT~mUxuzN?fEVL@xgST<(;o=A)c! z42=Q2Vx|JIsoTf%S3gcBqgg`r1jz{iBqGd!1-Z%kY3x^E&U7v2?jf5X7b46HcZ-diz~m8 z0#~`d6NPY{8*g9~8ilS)J9_!supDtLkpAHQG76aF!s&S2XQzJP`q86CUHbo>o+JY1 z*3GR=@{7woq0n1ds)JM{C45%>jl5x0OY`q7xXKpo&*N~|BWv@ML%KapZM)&3zmykd zl-e+1Y=k<0hbE^i%2RA2eM*+POI3szeOEN0{l+DPkDf!!9X>;H3-7VwUc? zq0wlEy_*ZNo?0rf^;Ib&ynv(A0c0yGno!ektse~5wqVM8cG(h`+vKGZn`6LyE+dRO zQ(v}=>W9UkOV_!;>U3no)+2TOC2}rhaYH&4Y8o^gx_C-e&)jfSG6)`ajgKSwAEqyN zS)$uX<2J{wrNJItLZjA-xnv-@w!IKqHi{*^(i`60ugo#imU+W@CTg_-Rpwd%GBSL1r=vV|~>FcHk`v^DT7pk>d)07hyP2s1CnBQQu zx+%-F8BUEQn&vJU$+U3hD(v3jGr2@ag6XW~9t!2w2nmAyi-h2?tPl?8$)lAtVBglZ zk_qn=z13$k8%+qo#9HEMYb*YGmfL_TcAlp61l6|^wTzKF42XXICGRfwGU$xA@vVIg zxV+-u{5UCsJT87!HX~hpTisNYZFOM|^}bIybyCJABWG%bOS?_~bYmMQNX_gN4OPN~ zjl(TDl1D12j!2Xz(Sz)L>rB=~n5dC{dT#TJNa0IKP)v{6#6~?!!DX+DIY4PtO<&Pg znGvQq6lqSfgb5-sS#fdSE76jb1ZACt$gLf|J^T8`=!4w?It~Y^k+ud=X^~7-$nP?R zR`VT($6_U}=h&^q4vQ(H2oZW8&&wv?--;tXHDdH&tw=S?c7nOVrGsrweU-*YF-}Yc z*LXX}RY`Fi)q-jJ!(4mlj@wOo(WwLBLtI5n~PQ1JTjgPKSc?RH*y<*JK6)p z7{4J&kIYxVa}7wi?aTUR^q{~7%>QY0Hj84!oZt(BxMWRKvzYon-W^3SiG0$z#yB-; zuo)m3h*Ul~gP`(^X4|$_kR_E~aLt~rA2C#S z)|Oeljf+-yj7SNPi8agzG8jzOj-N0i2X;c4t;n{2WER_*vKY^!szfd}nw8n-M${td zcGa2;iXOqjN{e=dRZx+IP-VD`+|QfCPY%YKfluf8qTFxPweOJ=_|q}Zb(-?ijZd^1?YM!m z^xK8CTP@%fOACe&9Bq2Iu02D$Gk4q+@RRJOhN8yc;e#84o3|c5%Cj)A;8kM*ZekO2 zGp~kmIkQHtTKt{(2x`d&r*3r}m#Gzd2gk`%qFy9?B*E5O6G*x+O`AvTh;V3XS=q7) zI7`r$ulj;;uq#R4R_rTk!sx7mM0M>+o|$yc#+rgi(YUtExJc`!%H?u345_7!{mE1U zvGv~D5Y3o01Fym)>rHB5)(3g9ULJE>oSSB9Ip2oqVrAXCxkMQR*4`t+e0Gn`qsOlL z)GR}j!G-mM3)y(6c(8OymvBEA+b1 zR5VctrV4nQtq0rks->yiNKJiWfKaLC(IsAA@e9p;377cz*uHcYbev z{>gW?4*0XipKJWx`Ofa@$Gp7$;OqS2-=%x^ACcbuV-f7l+YgMG-@SeJRz@Xj)UQfd z)$BtaxGy>Wd$0u&!s`{P5Q?sBu~;5R*SncoGef#UQmf{$M=}*!H0mexSK(kF*KL5& zECR`SkS3NYC^H2(@W4-4Y&1=rN{2$smp{3C@4@wt80)9X&aRsY7TiQJO}~}ouL3yJ zW4F2o`cHH9_(TqfO^$pbm6{$hY#;Pc!-=cBBlL{?_j9suPEBT8BzOJ(RC$tu%{~O$Ck?AHwRT3 z7=bkF9Ff^HELy5#(so&S<63fH)l2oTOsmt!^Vf6S~I)7Rr7(3;7aL%qn4Y5v(y>Mh1*w%d_OUZdgr7M4TX{J%mk zG+q5FKZFa>NPUg72g=XTQi4G$X$4r->{9i;?IOQXf7M>($;&l1%n=N$Hb>NJ*UAmF zn>^M(1b>x6y`*4y?VQTB&vnRU-m>7)5}8A= zVDnd)Q4OOg)%?90M_XC0=4w`3ii?Hp7o=@e0o;yK-+J%SKwIe7@7{Z7@Hl_#p!;3oL+4@E z^Qjpj-sR)e;OPEK4Ay(|)1#M&--nYYlNSW*xo8<>GyQU`tm8=pdP_XVpGrX&!uakN?yZjCOlVN^AE_~-#1kZR(u+Z|Bxd@$OyKoUS9 zlZ&}6%%aLQN%*a?`(2bSQ!dQ3!$sBNEgd-`r`IA(XYEXnG`mh%0ifr-+IH<-O z3mY4*n{a)Nq+D#uU=8rh@;tw_SGH9RtZo7sY=7rj)GozpEcdDPX?kR9K#~!&+r&TA z5`~_G#bNCw;EXhtR5(7`e49IIHzw=*8+$l0NzE{kD`4i6|=7y|n*-RQj zwsZzT6E$!l_s?n$T$&Vz5Mm-oNTyp zJBq(?J53(6TX*J?OBw0%Omt;|E?Lm1S_{&W+grD-4;{WCh!YU4eDUq$Es&^i+oS!0 z63u_IZuAV^0X8FcBICe;I>?aJh_#80Cf&ARvyjW$`$R*`nh^+#KVT0F+{`R*aV_ED z#`ihPUiq|HCNv)AE00q}7V^+}Tnb_8>V8;O_-7vS`cqi4$*}ASZ@u|ub<*V|ltiZ| zq2&00*oh51m_Gn!nl^qA1VuwXW(=iXXHdk>yun7kod`xYu2Z-{DsJ}9hP1Pwze)g@ zx2X*0w#Yr$1YJx$`5w+1>ZcKystemT*_EZOU5kQ|2Sn4-c z!!wx9t0v4Y@A5Ger#-_A5ETQ3S#^MtV#X9hR z#woJPrh2AmnI`(Ds2->%8?dfU9hV{3HQx%hGibX8URGyMRBRvkrCEM{C)pAtMw^MG zG91*DVm5|L*w`+G70|JcNh?LVnVy9`0t1$ZqHS`gBPNG5O*JZhxO!wP)6V%p^&68O zMk6n0Dj=SVO0M^vQmdHfVN@VF1ggLZ>Yi07HiUaO9$mk?eD7vs{I_dwZ9%9Z+4d90 z9oMFi$_S8WjJ1+mIvH=h`gMZ(G?xsF%LmFRi9R0*thu*qUJbfpB`Ak!*(d6$qs(9# z`||a#*Q33KCEdpA1`-t_;y}m#EMU;C{APHPTHTHD?PG3ko<_`|lSp_VO1CkCgW-e8 z(boF0&UbuCY=1gc=C(0gq?Vc^&~}Mq0Wv_JfIA{lbztGf^37hI zj~K@ahtX5Vo+R_IAEs!8Z5>-&99&1+7x$fpooe}gJhCL?k!AYstw*=!2G`$tc<=7} zk8a5(_Kk;0vlR8@b&4g#q`aYQRo*&zU88DQZ_#YrXkC@#Rl8 zKW*C~Wk)^HHFvP{I69T1Rgi1NDs(oivpRNyEYKR+45(8EizLBs{3_$>gcB~T^`~r4 zOWjzPXx@Fmsgyhx82@(m_msbgFiItcKx7sY9FOu&Iq~?vv)+&B@N7-xwq^tx98xS5 zglz9uG7XGS=g(RIWCpRKEejNMEe7+du!a`Dxo7zxyl&fMQ;&=N{75YGzcqadGN#At z*bb*Kww;$1HbSCOBBRO1eVu)tPR*X$1h~djap%^r%10 zBA06GIQHoEjf=8&lA}eDin89d?bxIic|5djqKp#9wt%Aoc}>ivu%ZGEF}31U*}(lz zUQF2H>W%^e;?&mQ{++M8KVjyHEPEf9_o-mV;P*h5Tv%Il>cKZ5G~{s9EHj8d`BrNV zkeYkpk`?nrHA;txBD(&PMnD&rIJ$%&XGsoNB$xb9%+AY8sqgB3_5sOPjxDweyO9oKG+zZxx4e6{@_G9N0=LsXq`vOZ$envY;Sdg99S2IOq4j^JI9SSU^ zFO(_O`cWYkpq1^OgiI65`_|iGd9K^$Q`zsY`Nq-F<}MMCsc`_Yl6l0eM^7r%c%Lx_ z;B~r?=u;iyUWLwA8sb>||i!^_W6i{BQT)6S18^=)D zb}q&CEkliJwWFHh*Xr>6;Gxde%17gw79Jk2eGAi}L?&cKKUlVkJmXi0S{Qda3?#ez z4Bj|7tB{{#$uL%W5T{tCM4{|(Zx{`mSfMc1Kq*H@B)y=R&~qK6CJ5~W7Ct--9;_*} z4Vjo;HHNZCY{e2pjT1EgZS!r1Md{Jpvaokce`{F znw%*Jh+-BP-*?oqAH6F}fC&)hkWDxbmn=aW2USE#YLhD*4-N>Z%7nw5Yr;+5l|C>t zsaoSvS~y7+`$0|vf>U&nnP0`&BX#9C{)$CfJhwvAjWO35&kFcA+|{aujl0gJ&-Xrf zVD5dJyLzji8H|8U#uo^X+VseQ zgN~Mw@D-A(2NIPnMcP3CV3u7A9Xh~!GZ%5=fv04~NX_Z5@q9yL8a)W@r-t4=Ahl)Y z-HQ7N@61grXr{uDghE$ur8DO)GP9q2rZfMkHL#YXf_}hLL6>vWukPRTcD^~aL`n|q zGfbyuRa=5?WYfV_$@$_(jIRX$blZxFa>+bpQxb(SQ4-518^k z!P415>4(A~(cyb7vsUB+@gYeFNeOf995~m@Gd;pi7zI615o2Kw*4ym2hb~Z(b)yw_1OhF2Px^6KDG8{c@houwn({++fk_L{T z@cv?|53w3kw&jd&O+QTG~%LyK?}4uA$84za7rGIf5GyO>$unI!r+3 z57bRX>g*BgrNtq+y=e|o$w0N3RHs3sjR{)QN&XCyQf;qk_e=h>bb`%n{Wi#p3%bE> zmebe>!|q*`Zs3|#FkS^u4whoe^2UF?+ML7M*;N6Jh%2UEt7knLV+G=M%f`SKpTyl{ zAP>?d)tYOpJ_C^9v#ovP-3w)Tl^7Co-GphjkYo+Y42O@2iOAKbll5)QE`dzSNV~U= ztXEk?gt@#8c%;&#iY*Ct))9biP7V~(G%?Ai$8^%NFG_pQi0Oi+Wv0Dm4MC+(GnCi! z(&retX%1u%f#svyp4N&!X(}!Kp_J2TA2J0oiC)>>OEhO0$w~SZLFgqx}`#u%~3*lBVQV z)Mj3Rm-HlJpj8Y+a=rYf?mSp%HCx4$zee20*SyqUjpxjuq) z>mh~sgd&c-3I`#4Z|(4yJ@n<7kfuEUI)h)W2y)YyDm*yY;xC8u^)4@xylyhy^SGfz zj%9=R{b~1Ro?M0>Ui!4cnXj6=~H`?TgzRdqlKB#Gl#$cIkaU) z3(Jh;`IB0>wO3+axVe9fmnK-9?YIb}N>;*tpm2o3#cQ@yHuYh;MTG-AhY*h0tX{>T z3ZWa0lt)5TKZ8_g=qT~5BC#n7FGMyN3lX2E2cOFwZ-IMRa+{xLcnCxv7oTtT(s#tU z2gONm2rGGMg-tj8>V+Nhj3X8m?c^CE&z&q^!Lly;$$^4fb9P}7bhs`^>(gmb%qe00 z@y_$vQSUgKle52L>oSj)2EH-4ZNQa{2P~Li2LZXJs})gd4w5s*ANLcTRX*M9k_2d*S3kqaI7BO$VBoy z9e-$Y`(bB_dN zvPUoyP(tJ~(%Jz4j*@Z3c&X5-vjQ0$jdhm_k3GqR#Xcm6%%q_4(4b?d&rP2XO% zx5>m(+X#&2()u`guk!%zOnz_*P9@6#k=kmF=(jiJEIaE?m)f#J6g}Ho)vXrlt2Q_t z;AQb!dIVa-JF7?+>Hw@b3^ku=P=cKI$8ZOtGo^0{0P1uVkdFV-+ReSm*?~2IC04xN+>|^fY za2J@Xh#})h)l0P`gP7O0lVg}si3jJxeKNXQ`@RO4Jj*c!mDaB&eM|{Ba~bCW%tgKvCZDsf+h}4I+lYk{z>8w(aB&4H#yR%u??H-gIHfty^q2cA;6O?L9A$W5G z-2shD)t4mg672bWb!U4NT~+oujVOK6?wCX&wRM?`LN0g2t#p`K^`xn4{TGX9X4eH# zSz&16z(SS)jVItMH_*xsHkoIT9EX>{(`Eksr$vG^RwYYt-rgNWCO%e@V=Y3wO0vtO z%j&D^wJ7ZqHUv$`V%mH$BpNw|@vv^IgI}|<`+G!iQ;a-H`3I1EW>Is34GfqE|+Fo%Gr>#1;{od_I4{olI#Z*Z&;^#m=AKv~`b;R=xPwt|v($7Qb4jb#< zum+aC|!ha?7%^>0Uxy=A32%;d#QgHsigpImJ9wv~;S{?9P$ z1(s-Zu=8y9+B{;<7UzAr%i{1EH&f+F6F)9htnbaq2KfUK^ZED51c{&M_^39BcZfeE zk|KOEy~yp=L;(AcJw(AD>?flOjvIn4F9c}%sxG_t4$SQ4oU1PJw*_2Umud6@h8ELf zG#Gv8Se+WmPGefRC1amfJQ>E=7GGyKOquYZ#HI)J;sK+1AbsqmMqa3msRv0SFmYn{S2zKWB-FC{Ga>F63WA7!i@|v3#=*V}aW9y?sJVWp(8x z&=x}m4ikdgiN??n%{H2|oJIe#H4|UrkznBl8xJ1%ae`gbF;F;G2TIaiY=1r=8^t~$ z7zuR~?2ZIpF1#P<--l6VLZp zRm-qdNFOGHva`|B;rN&hQf_HRO(@7L-#Ln6@u2VIOt7QDhzdSP&zJNbd z`sHeqia7z4WOWf#)c_hsT!KkH4?`#584B;lAbcK%E;eUzTadPBsqqQuU6w~9(n-(s znN^0nCG#E$$NfAEUA)5({COC<6A*&Y?&o3XpNFAKOZYqtoi!n8I9R1{lDOuqSgQ2{ zE6HL9->tI#QZc^@g(!JSKMz9(IkLN8!^(S8@FFRXKWSm;Nxam}W90eWi12Z2stM@y zHv1eJp7deI!e3Lx1g;W(EohrA5!RF=q;4I64BoOa_9e~Xg_@6u#b}e*PZ{H zlK)a~qcd@$QRn|z{>5`t`s00-LQV6M%fEbX`GSi6iBpPVca72)&n@3q>3_bjv>BSB z;Dd9^AD;+8qz8ziE9aK?RP*QgW;)``6Ab|3@m@ zJCTvFDT@Bb=a&DviuMw+(lAB2|McAQe|2Ixxxk{_-#EAY->O{iw76R&O8)J0%YR2D zdx^r5vqZuF@!ay?Rl(j>1b>cVfA8G#|9W!IW;lzI|NFV+Uw(}SPa|G7nkfB8Ut4~x z(!J}`M^p-b{Mz!a3Sa1>A6QUVS&u&UUt9jmCqm?X$cq@I|H^C2|Jf@_%VQL!|MS+zx&!3zQDwu-kBBZ?uYiU9kbs; z{k?DXyh`Y>SG`LkaV#rw+LEvWr>s_cf2O&%lD$l^uoElO%SQ5kU`0+_O12MJsnfV> zVv?^cnAqav>^#ki_YX4o@X3AV?a7Mt!d|f;E7VKFWn;H8Gvb~-?Uf?!O-GEi zXGL1IpGlszA3Z{`o*#erOPqDpC1!p{>-Ubn_uZdQPr{S=z0pU%@vC3>g6@!Y&*s6) zFP`V(UL`v`+5C_ijIuU&)=HX?RyFN*e8GwHHY%JC!|DWs|I|CWoSCYNlqU z*%z`^ecS5pnW388oUE#>?wYRKR95w6DB3Wvzyh}R#hzWm3&UQ+SlestVjuiw7_i|7 z!>}I>!!O3Z8GbSh{|EkjBjVhCnOW7OC~3T4&9F1`_d6#}oH%jfM8t^`XK>|W@9j%( zy|v6gzenWq(pa5i+*0WpTVq z$T&Oo77V?DfzDdNC9<^0BM)AaMM*F>H@8}TgGulG+Yfs0TdIdWvLS5l?QZpMviW*I zsshe<9O;QA(b*Ij)xIta?ga+i7Y|%J-14p7gq-li$EDN+Z>J^#o_3CbF<_I9q*7eZ zXZd9~X~{)?9$_9e=l8sH&=T_tmB;McgA)MhUkYJlhlfl*Z_<(uW&YsC{SWRuxZk^c z`@`N3E^lmHzJ340Z`lSAs(g=JT5e?TvTdYGn4l`La@-?xxC4M&*EX(vK#j}q-MD$< z{)dWPzJBBWZG}u+zq8T1On$MA`!}vUxJlr{-3J?Y@7%jK?Dg*HqN&Fd>YqVdxli^L zy0*>5@I?80pFbqoR-7!c+zZ@pFkuN}=aX}P>0aKm#*9XZh9#^e^7F$n!8{;#!?v8Y zr!(n&`|-)i(dx>|vuDqSj}A_UhsTeI$+B^uu6)O_xqM2>3hp7fxY~P<)al&)G3?zO z6QTL-&8@xf!E#Vu5$@lCQz0OGv-ykw${QYJnb^eGC_%$bzH-}RUz=nW?zn6U%Hgp# z>!R}UBz>D6Zav|UT0Hk(+TNcWr)MXR*~!%%5cvVSzIpfa@X>~!sr-Pz$35DuK@4>S zs(s(t4fR@S)+$O!vAZ0H&{r`Y9rGBp908`7OI^Ahi>F6wFpCfI8gt%Kxy%_0nP+i% zpm{;OPr8nf<8a*7rDp7=1SS7d1v?`dnTo_Rl(MuU&h?%+h4aO`TO29yXF@NK@H1y| zG~3)T-A2uSp>~K=v!mhcf7*=Tk>AT6CzP~}=@2wiCL`t2u>HmC-Ra*?7t(VbPl;mh zbK+rZV(Cu&w6%`Y7;kUtHfR**y6_$5Byx#ciw=)ptk!R|0S<=1Y972zlQgfu+drApy-8RPnc6CSAD#;4&agEwtKeV)<>#BwWb6hX&l}t0euchrCbQmfLFe#w3t=Js`7UQ~Gbc2q zDHA(wQ_43@SsW7y&5mq$xY`zm**qyPj3(R5tRTuZY|%%#_p>{VrBU5LoeSDy(T1r+&rTG! z0>r^vm#QsvOL*jods_l!Fh8&>Svg8vNg8;Yhz*xfCR5_5H3GyvmL*pGo;-dCjJi5$ zQ%NbP^rM~1TB-9iw>-L*H8kVmz+Db4lu9XAM8Vl zwYGrp*6PeSni(=-nsNmg%I}r){abD0n=YXWantMeZ3EE zi@-v)RJyD8=`WSr**l#+PN9YAr9Lm@Q>!Q`TEA?^$McBTa>$b55@%;`JiA44!Lo)* z%o3I~+1DvpW3FU}yMW*Gtn{Hw^t-gkO)(#Iv_jL2MWFRBd$dVZrSKFf*; zNcyxv2+XRx)0 z+E;}#m-&_=h$Z|r)mT+YPU6jxXkq?Yb3v(Qpq3X;0oq+(N>le9pCWgqppi*HC{zts zQNT8gX_BT`Ts5b^MH4bjuvFf9ETj@Yr~t?J#1)0swRpQ?2{IIWhcd{#k={;gOe3W; zBEy~JbIidIx9Ur*_(f+R2DS*LRd$3hC7DhJch!2GS}5y;w8p01jUCr~g-dS!#{0ML zY+Soqn_tr>yBw;iGTziZ0{ec{vC~9qxAa}qjDXe59uhhhnrq}Fi(uA1+j>B@VzUqh z)hn9;Vam44txk-P3hJ*eYz0R~9$jo-E#F=?BbS(TaJ>gf@H$=5C047|hi^P>;yhjg!8wQj`5 z&h(e=$#{EH4`-Xf(_S}RS1BjCt{IDFUt8BR3RYlL$mWC?V!;gh@sucWEdXU9V&*i} zT3+>6HYf&{u@E3zB&rkfjeVW@CT{}7P<02WjHw7>!lx^%YofY5EP^l#KV>5^b8^Q* z)~mpYOqtb)=U#O)SK`8ss^+Q*SXDz=##eQsWiLOh(K(xNCu3z=BCpNi$Q&{a-Ow6l z2>V9Q`aaCV_c~l(hDlOEShrx?!BQD0IW+zm^skJ`+lg@LED77B!4osPy-_W5v)V(a zH3q-sRwt_WrSP;wc8lh#m87}lzR-auhApDSXzY`dM3Nz44wDlm%{|M_stXp-2Q(e) z#m?EuY+OGtN-qid#>a3VBE(ry)snX+g^cUHPEqLomLo)w=LB@_Z~$6?CFCT>++AqC zE(;|$c^?qD^BN+MoBuejpGn+uhSZ7>Z&Jgato8Q}x5j(=$|Mz(HO>*mFhw~LITVqR z+lI#@3)^42+4Xr{X#D&lpc)8z2y^s2sqDBd1u-uE(_o2`?*zA%%EpZS@iYZX!_>CQ20$MsN z+G83f6|#A)+sy|yjFycwc${5&k+Ju)8UgzrgiR&6-lU2C4FrRIQpaDMMPxs>JIPQ zw}Ib1wN^LiY@cR92iFGRaC?j+QMXYy9)t>5v^=!+Eg8X@ty2sG*#vWzqw9yH@X7_G z*+`79G1l+%Ck5%thY^Wt&FzWr+>;Gc_P6g6HMuGon{ePjrs|7+p z{-=6w(FDyq+W@TFE8y(aJPO#0Iir#2yy$%zEqi~~2v~u|JYlbE(%FOg#MZ0R*=Is_TH8(ZUL+O`{)|`<0mX^x^TvHb$-0d)lp0u5DeG+TxBQRTETk z#hCxGtUj8&?Uy4P9BD>4lJOVYPa?&28@QS?y@0w)XoKU;$zCX-0U_>8i2wsdb=|qQ zGX2RZ8*V$(q0#`*qF>Rx5*C4;8ql;5&r!l@FI)%SLHl8v_5$U(Azo27D`hu%xU{03}ARm>gE zDcb@qv5E*~kc}15A7?l2faxkfSIETIwommSQKk%VHIAMFz*?#bv^KrHwVo*X4Y=5M zcNL_TiL5y~naX}VJUY{!p8?iwyCCOdhU*ivjdR3<{tB&0B0OJt>XHE?wR#u>%dG1! z&O!&2qoXbT_wG9lnDX>x;lyk|dOp#m>kY8Zs~Tc;<{4)SIXc8I!|Dd%OlcAXB_`?K z#AZY@rVCRjSIR6f>q@CB&9YO-IrgOkCBIA7hdF}>r#Z5Z-D+m%N4f1Z&HeK{fU{Cl z5jhFQ%=V=OfwP8eSV=8D;)yX!%e{gFp$7?z-Ko}(ZnqquBEhzE%LxO0o?Y9~xLAqo zx~|bZ1W-i2;jlnE0=$;`-dtWO@WY)9Lzt!F+m&&Co-inP_mFCEml6DBK>#k;04&U5`!Yfvg zP_L21l1a|mq7Dc~$zC;9$lM19Mp={D)UBm3yrV2B)nND{*^oX!w_{WVQM5RzSlfOE z_P#rAMChc4u>6?=b&5T{b67fyqcXffzD7uzc*vIdpfkw2Gc%KkcHpg~7={AaAu?r# zC0K=DMu6h>&_Gzv(^{npM^CqhPY?IFLUlxd3V{_nyBxRLW(Q__GUz|Je|`BI{fl@# zxc;JQ&PTu3RYc|Y>g>{CuO}xnkr(Xk@3V1d;drjSdFpe!{DFX~7`{NAn|8vl@z-wD z>T1_X@Vo2Z$5j9Iwu}#T81p||e@KbnYD+YO9R)u&-^Z^s1+%LHw}=`3-PdL|pAFoK zEWprB>y8og_b?Y(y*pYuDuHC-*xrr+F5MfA&@xc=rKYf(FFqWBE z>1(mhOSrKXSXw{L5ywZ*wo~~>$4B`qX}HsOIRbb0%CEi2bGO&o&?fDe9lMoDYNq`a zdvKwi>&h-6#@4z51%m)l8E?cjwfXXft+-&NwAkuKA5^_uJPh)}`14 zMlcTg9xTd52vXsnaJffW>tio3=~~G1J;5L7A75@-MJCGYHQRea*G7$0=Ukx}a1{eY z4EaINf?(W2Gi}DgjM*M}#2pCfw#6wS?(PS$_0Hfh?nGloFk4@mskIbr;cY1&sBSUm zX258c-|$o(Rcun-L>vJ5A(mQ;05I@ZL^b7!$sh{S)3pOI6bLE2&`LXvYNyc496x$2zNMB2 zcIb5!xALFR)c% zNe{S*EimzpTj#pS_<|SPqCuM(RD9Fa%xRnWg*+1aZDlnc#68~Es+nF}^R2`O&gnr7 z!U?1&RRq=QEYm9i3V^P7i)^%7xxKYE*Z7skh_{+VnB& zYlQDku~%R9RD}<$8unSezz*sk0S_zeGN#C;T|2Y58#oP&&Eu0IEcMK*CxY>- zh^Al`KAfuf*-y5t({@3G*sIXv0lPPI=_kK|j5&AITdXN$^O(1R2*z4w7!uH@ThDrr zDNGjoi*|qDw$5b9UE92L7i%J@QC(|%FXKgS&|~g4#L^VPJC94B_4|a40%+EMxKGgQ z#~&T^$)oAzm^I_=Fk!u`l$+bFrjS(|c}V#nwcvydB08{#q<-B!SVEE1=&G%ePV0pr zx0Jq)DP7wT%@kR9*!z**{D{cq&E3rxM7O&+ESEHial~cpfgt2W52GYul3Y-^%BfHE zrLPkYPj^)Szc-sPBn*|^{-(`khlk&Q*m*lfMRP_&c3((+gg<-Ja>1_seWE1q7q{xl8^)U6Tr=2ji!Q=qtEBWh+=R zDD&FyZgXVMsT5sju_b7E3q8#l=`vJw+^3w~&=RkTTRNCz#C_ltyK4T9YYM(Mk|h4q zL88f%0l`&ohhhsn^u^)HWN$C{gsG>o`gTt@Q}$jriWI^X2oa&z3d(pb0LwiN^kfL( zYKuVpotk?a=g@`TbqkZCS36|9KS7y!W>kx=ZW1x|#QG$WkY2JkK+worZwUNQI`Lq0 z>7#?CxFbeSD_394DLs7{09HTlx`?caa0|^6wa_CNDMD4_ms;=umS4=vZ#ZOrcl}K~ zH-EtlhIq7M*^4-cZQ6M}d}saJl>3XWYsItguHW)!(k9~B-Sr>XGt(X7*&nWt^vsv< zcs5?2=vg|DZ)uYrtv}(}UrMW3l-##Km|qAv8xN1xe?rmUm@8kT2uHD}>p!K~U!7Yl z+)h&~@@kRLQT2~3a^@Gaq>0C#8R;wST#R>rZ~Y&I2ManmP0TNqsb;_GA+QHkhrM_r ziv23%U_aAH>Bs3D7Z!f4zmoh~QUx}Z6nAorYwOMT6*f{m!?(qx@L(6j+t%adDN&a= zD7Spa(yB@va1HMcnt{1rPa>7^^vt-Ea7280dj3nd*w5GL`Q8t-k^Y0jLykXu``I&n zey?_gB{vdob)A=gRiD`Ha}UtZnPzf}gs16{&{F(b7H|@3e{w=4TgP9z&Y#}NuF@PO zC%Y`HC~~?2?}-_gsN zSGHHaH{snsQhaTyj*s^pYHx|J-B*uyj`X&E z^{K1Kk1UhO$z;Sr#3f}UJm+*S-|@X*a&e>;C9@8&ky;%^xqf3yMZ-i9ot(Z(I5J0K=Od8S|BaG|KRb`*!KHu1fWr z*81Gyq0ybejIyHf(35>}3G)amUe)E|jgC{XP_x4C8HVxN0mX1=tmnXB8NFhM-6BZg0u0*x73yq$#?Xw64*~TN% zs*=Iw;8EiU7F&o5;S2hMQTK?_nurPK8q?VT4oi(9Ix~MCzX$qkTqRoieX120?wLU|FFD8j>|1m#DrLpEgiy zHdyM>n$5Y4o0^~VCp{p8H21B;M*CofSVQ>w^}U1Hf@?CAJXYtr;zs-X?UgCJ2L&@t z((>y(JZscx+Pj(fMwnLLJD4^c24d}Rpicd3 zPBTc|JUb{||C(3Y35!EvXMDP6OJ3%X77MYr-{syR#Hg7aG}-)i$!XFc5YH3I#6qW*~1}eZlW~Zic_wf@QQ1JbVU*O1WlIM-P?Mi3tuwI_i@R*zRA|o>zrcd2qK}+ zoW(yr+ygeN7XRmwSs(a7nbdf)0*2N=xv4C0kU5}>J<~lzxxw6yU4}$){D1NRT8zB~ z>%LXsdCs%qg;{3Xod|9}t|(!k=1S*g`m(HyU`$z3d$E#x@GT*vPi)oZK%MtpelR-X zzH*=SQO9=}B!85HEu(H=3+f7sfE9c>cDGDuA#&tJm6#s3b3MVxIm_HF~DZP+5aZ0C$WMesgQOUM3C4Mr@l&s!p zsZe!aSRWo$DaMPR?+jwRr)ymfD?Bd@7yZ#&g~2&^)KEO8Q#p7C{h((5Vx{n= z(%{w-#O=xyxpkZPK)aYKabF%17=VyL8H1FV>T?@a zheI|n>QSUl6BDG5GA+iXqOer0%-Onb+z6YW1PP_54VE4;0tuwW#S7tlGKA1A zl6;U0X2=(G7LzELGI$0Gwc1jtJ*Q()DK^}emT9m`m$Rs;rPrp*23mLBwe3nw2U1<( zj9z!cm!ZObihbSoa}T;P8uNmE72D7VoiLr@L%v3amB1{*Jtfj#KcbS*dq?7wkDPo1HjJ3%GIk_xR$g0;h1ITKd3LEQ= z7FKPtCe2?A8}qB|Xw!ghnuz$0sx6hKn9ej&W?C1@^gLhki-3S9SAnFDEWYy)D;Ls)LM7YE=%9-*v1HJU?bqM~gF&KC9Jn?FwGA0gfte#r*&(3onZ zjyMp$cphG5LC_tEDwSqfntb>a+8J1Znwf>94wE_Jd#F$!+MyK%uew>|$r!W^kVm5w zuj4fuwyd<~H~U`R_ALoyn+223=k#IZm8NhmOQKi{azo~oVY3#I?Sy2QgCyhCiM)mv z6CcKDjRda48$P)Q`E71Kxm|4wdiN2OB9<*sDjjMl(9HVo7~uNK$gbsYfwr}(>AHoy zKbXzB$TZt9&np|wN}r*82%-I2)Rl2y%L4&vX8adpT-RXCGEU^+!APC6He4gYryWQn z$uB)Jfsj<&;AD-Gor8lmwX8r*IysegW@qg)(XZXSKDu@J{To+!!~W>=-{0ZMQoR=6 zKx0!rRlLxgW5jdsT}J?{oKBAw&0++xA5(s1&}`c>bphu!hzG+H4h;Swd9&s~=;m7B zo=uhjoexg#TT7K1?b()5V}=H`BLBE|;ddBm%MNCsabOb;@aQljf~fa-K_4q~5$s38 ze$6r(`68GZotTQH)W4;|eX65Qo>NIhs#+#D>Aa-ofH;f6bH6bAxgO*_0Yd)>uORNw z(2@u7Sn?bJnOZH+E-pIZ#58=)2`=mJp!QoyHWsn0JqlcAbD|(rPJg(WFiR8%AgAo$ zok9bDZ>vufTGJ>y8_gHW7kc-`+#b*HFpJbOTk|lZes4WCjy*aijp*|{WT_2(=HW~J zM1gpi^_Dzj7gsB-KLH@)4?cDE<>BhvANSV8^Vq!6^N){R*78M-~ zWw*=}flv-hruOuCfkUf=^H3MR*zUpdTk=0yVs6GBGx;0KoA{q{6bJ6qLnTVl;yjlC z;(c@k;#n{_391?Pe!z58#1<$iWy_X~Vy*+maeDdQl^Zu8GA7Y{pR#_q-Ew)%G-mqzI;IXwGMF^TfmWAfX%Ck9_EzZo+MDHwAe5c)U4A9fI$y zX=6T7dO$2K5gDGd@?v8yvVFdzPu(3F4y;pV_WkZ*SWYEK4e@ z%URY|W&hxmfEm_;C`+;yMu$xA$AqFw@q{&DMo-maJyEFJK0CDXo6F-|@zI6eW&Ec2 zf|SWeV=4fMFtsh6Gr&CJ@B)cnEZx+&7rBLOTk!Nmw@a7g$Q<%HG?#5>&rp@^B5!9L z2&eUKyP9vBo#BYB3?2#E6dBY3Iaq>N5I;*3C@4p3N59FGOQQfyVrSDm(u%K_6N7j; z_FRwcnqm%*DRJG6%hGSqG}zH$!jZja_`6#1MaxUuyOcTYCG9Q^Pk7cE%d6_Q zFbkZ)Y^%=Fu}Mkxh}wvn`Qg!3adao74QjO&Wb&s0!JH$YnFjFgESI)fTorwg%py5Zdn&JMFgks0q$dqn~QGQfM*vw|Nerx0Z zoj-e8r!Hg~Vj2sRc~mEmLCT-5IWgAUQEU-ANW?tuOD`c;i|D%D>qjOBC!q0#&5dmW zog=_r#BPS|%u!U>hkPydd|ot~OrGG_<)~H(lA0ZgXozyubj15DOI+co!DHo7Rx zD4P=%f6#4Lknk|=OLx;6E?>Ygx;(N&MfbDlYeJz#go>SCN!e1{P5Ww&~_`i(coaGXF-Lm_3RAip4Af66bEez=0lo(?C3s`k}ng; zg1S(Go3*C8C%m;aBeCoxjDP7s0F2QV~=m?A;PALQO89v$%1kOyZ4KOAuE+kgqI9=2^0lrExs4K zFcY=?lIn<6*YuAq%JKAkSr!2-ozY)oavB$8nzW7PUoRhRb8bfxo2{iU`1lZgYx-wI z{McAQg@pt2x0($zL!R4Oh@rJCjx26r%@2H$kDJh?b76Ejvh%x$DPx6~2_&kfU*b(o zo$C91pf3?b(@Z>Avi;qvdxmda;4=jcRoK!_^(!-z!IuP+o;{M~LqUtUup-|>NjM@X z+~d$Bx{{ruij}$>;(x}HG5BUMIbT=X2*-Z%guo_crb;HW`f5T&NW6*I-+IDn`aa8} z`(XK6HH%Q)a4_bPcd2aPWH9Qd`ZiSTj6<@}89&1^A!tJPw`E#H2B&m4p`Y=^_b>G* zYNIp|Dx_P?o}(sV#Uc5O`O9LobtSQ>UkQae{ zlLl0@r=XvL`8;rxU@cWT4s=%O1eQ#&^v`r#3i;xc)xPYC>3{7LC-SGuU;CuB(mpk% zw+MN9Scq*tMEQuVe~54#ii$!^9diSWYhjRy<`JZ7#>z@Y{8O}<-=#HELM|~zOc?Qq zLX|4h$hC3aV~Uz$4%76Pmk$p2x5wN2+G0x&_MZCBkMW=;xVcf*EqRQ5#9Q^w!6rvP zu;Bpo!C-1(8I_IgW2&?uW>SfvWJW zn!oT2vkmUmb)S0=a{Zs>~p1^5Nv#C$fK z(}9zrlI|*&{wNzs7ra=`X!u6p*HQqF6o^IF-{?IIGAWGy_<)SH;TUW03`13uCyW1P zyzeusmt^R6*Rn|~Y_MGViCgYrp^Q9}IU2ekpgH}g7XFi{Xjp{$Go-tNgrYD`#F_f8 zgHx(<-3ze;yKy(?!859&u zX()20Q7AWKdW&|SXV0|2zDqJx*wHw&Ed&9WBMsT;sim5MH?;-EaU)C>9~M|0x1|Ui z?DMeS^oKc0+Z4C%&MH*Sqoc>f@=h)Kqsvq>mp6#2!&RpxSE5N ziXpI4cOkc18|O6P16GXCb__y&EXzu_I8w51rSgEy3hn^bKNHW$<{xW->!) z$H}kxH62Pz9?&x+6NTe_e7gBj;2}LVZ6qrDl zCNM?c|9B_B?_tjYP{{q_CNt-t~xEWgqbX+b$e<62CHC&XQrf`# zn#41fXMY7$4&Qk=UjFH&zt-1AkvTwUb}D{c zSFw53G8H*$$i4%rINAH`JA2VtkTAvUSt(vHqRv&8Uq480Idawt6RL6c@uU4jgV6I% zk65=S1A{!YjBj?_lWk>o#&o(jNSw|iIzcj01%+v{`W$d9=ZeoyXK<$6tG7#IDHZfe zmd-1alP$OCMI8qq5(T+SkIy2WP=Q7}<*>wJYpXy^P-$(hd)IAM>0<&mBL2OI8>kC5Ja@i=lT}}lg44gO*qa?9$ zFU10eSV-VF(h^i&t2VMjsSS}61rRmn=G0y6Bp1TMitgtYp?z8M@xf?ufMtSt#5zl zyAMD5=;Ocrqfh?m(|>abW{k)<2^$MSiWtP)NC#dIsk{^k*N9OZ?0THUuGorwrbm;( z*WWfKcepysWr9qwJ&RlMndW(g7`pk0bcui6@`kf6DU;*FiMU5!InMB%fuBI<$ez8 zt#Wam>PuP8V8zU!NDc5P5%A)~}Fd=&x@yTV35G+V5M6>|VD}sFL}_WPtp5{oexQU+a{P z!cpemUjKI}^EW$XQlygjavCN7c>QOT{LN0uDrP;({e$)YWKOFQDIR71)Aj$1GJmxL z3qecNcog}^>;LN+h-phSA@;wm{~wgR&;iyZwT!a>{V&%4Pb&Owr^135kf`&2t^eQD z>CdmD=z$c+5as`$TmR}SROpUp+VJ#JxBj(PZvCQ)eWisPS*5P|%U`cln+`+V`pPS} z{tW^6D|MNWR?)`qymIS;iu_hxq~ke^qOZMj>xPPcwJvIIj3}`F%B{bp0>4ogXl&Ui zc<+^4KTyHnt_#kn(^2@tS8i?16rM4;qVVLEThCSamnz6kuUo&AUR9c2)cT`WZvB0$ zW%9>2sN&T>eC5`EtXIG6Q`fhX;@v-b<<@_}J4+}(Ge(w5t2?_gpWEA);ukCV(%fjJ z7qgYUe!00|MZ5TC>0ocqob6U((Hypy=ZKXv%ft+~GVNH~qj@Z9FB*=U!$el-EdI3u zXHOO@@=Fbu*`o#W-QIQB%Rw~Us7I&s6R*`54V=VQ9NF0Z*)RA-1L@JCiw54hq>BcA z4KtzxFJ?p_=&1R zV51cA$Sx&`1@f4Xq1dlkoU~qR>(S{ZON{oSHU&n@>vdspFEHS!3~&kPKRozWFRlv< zb-ed>YT_mVH(XwaBl#E@UtZ+*|CfvWf*U`_MFXrjoX|&c`)v8uw1KV7i>U6dPEKE4|O8&|H4u3o->ZFKGKohu)hPaDg8a=Jo`{oniG}Nk0BN0NVkD7 zBmiL+zPvFMTRimrGW3)yKO)(e#>jcV&U&XrTk%<3BU04OCq3LE8?L^Z=S%xF1Qu8Z zY&ZYPZ`m^nVcs^9={Ko%63jtfC-!2~fvjCx%5=)0SieQj z^Xt9!chEyk-M81(Ft|Rt{_grJCBBlxk)LXaci&$BF7N(QdKWgtzpkgIzgBNtSxF^p z&idJp?cGcZuAAh`j!u#ef@1Ouk$@3>U$?!t(N2T`aQl|cG)X? zgdx9KxsVe^DZwm@2kBuY>-}3+Bndw6G(hj0TcGk*1W_Xv9dE}B?V62FO-WYsxX9t? z9cX<+Z`M0qZGKy;=h|FUwT-HK((l@mNq(m$?uUNcmcr)SlFpn;UFEkHrnc0}Wz|KM zzF=vme3vtnt5@^ckU%)mI=zp>88?g)miph zO)9dw^YyohKkx$zmr)|GqIV7SkMD4W2E&fRyYCPTOE{FA~+PA&8;6B2msj5ml7LujO`omQqmSMOezY}53s!N` z4zKn32blaz#$o?eDV<4a2vyCl?b~VUVI$)tWb{aKwaua%Lf5Y2Lz)-C1K{GmHP^(gm99r#f$`Q$6t-|Nh^q44xT=?^ zj#iN>V^l+-M@}WGp4S~8@WpM!d+^#ir0aGiew~;}=Ku=}rVKj`Q zW9a0&Te0@&m^!Mq(?-YJ@{d^;TS6^=I*#N^(^Rh#10@71HY#)REX+%(ifLzAtQ6}E zKyezCB9Qxdk>5x?QCNjinaD{u>sd;DwGz4qfJ9E(o~dvDPG$57vQ|`Kr3zAv3MK9A zg?a(1YwCMFO5THk0914&K_H%GJL6;U&6c+;W1xTc^8F9WurZsO%g)fAwR?2P9jKGN zr&VU=${XDmh`!=``oyWNt_bp~FEM<}A#1ZW8Wi2|@>8PW3)iK8%_&jKaitBft+DbT zqv=%V-@`eZLVB|h02m=tI`a&MgQcrC?xECws4%{(?>)FTx_9l~y&HFKkM#ZW)vFu) ztPZ=Fud`r2JUToYJPB8=2EPK%C_d4nQo8D&4N|MRl{|T~A?0b+V97NVrD9nETCS(t z%2F{!fqPVM1k;Ew?(S|qu`N4KiRc~r-$zB~T9R-)@O6C2T5_V+(WJnky^2^BSlhMF!VQQLvYVQQI?}e+eyr_l9 zPL1Vt;3OOc(`sg)h!BJb87BDxF_;0J?!yrEcjk1+*2=Sbv{U!!n6oSz8=}E=qeNIS zY>s#W9C>Dx8H|18*wnEjrJJW5hS<~BOk1HNwSoiYDWg_8pzJ47eZitjaTq>ZlJWcL z;ok1He{X>1Q_}NK?1$^f7$+KTsz>OC(ii1Z_&LS@oaQX8#M^DZV28|@^RBt5-&d#q z8$47-w%)mbnnH`9F+9W=%*k1Rq&QAzGRkq_29uP>Vx(My^GMcYoA&}p!VCk4ASatc z&bXo}v$zzfNY13Jf3bd7=T58i&y=fwdAZyok}Y#VE6uW}OzfBb;Au~+gy%vk-11NK z@8cZ;cTcCwc2QTqa|~%=x|6m!wV;`gwBshGlU94iCLD$VwOS8_GX<3gh*Gg;q+)ZhhiY?>cNxdvTQ9^*oh8Q$ zoQI>AIs>~XQ1G($<}E8laF!yCz@Gud1M!0yB^*zUtBE)kW^vQ*cP&sU&1Nu~;^}i% zG=Tv45~Jz{Nz^P8MK>4FdHw064yxJ> zDY1*52LqEmW?-6wJjL>-c7|?VpBBUJ_9?M;%ta%{Id?_Pr1YL3nh06SCEnD}I&A6e zKH{524d!@2z04V~;wCTKHg@A(xiKq5=vsVc6?84BqItq5_L%uhx@vq9W#$U2f9PPb zE2{BXsM~T+LUx-SrkZc!c{Svn+)X5b<|v8IFGt#`T1SYNN2dpmcBLBF87qs^O#Sef zPcPuw0*R!QCq!q%ihY>CGj^stE3JpeY^AWRn&g(^(|3o;1u;p>&jX!zdaBMbE0mTy zHK%JnzW#PQHG*zC5DJY*rYabn>Rvli;CWgO61D6dLKS6-$CvQ+x2sgy)jSXl7KpXm zc7Ocwrd?S;r!8xlbcUGUCLRXJRqIX4JdlWbyh)XI*Eof>`MLcVRX@?@k2D`!Qy@W0 zpWrZi@0qnR`b2<**5slK0GsnV9$s_$o4s_m5NTJ!7WE4oQiSGFf-187Z(=2yjN zjZg_vXmLfMSKMR@1gwP$+z@4_L?mGslh*kBas%xhh=G8qs-o>jj-domW&|#+G$#YI1 zSG{Xk#B=cKuvNavCE24E9bbtRTCWae&E=I8*pUY~JwR@xAdi+y(t=cvQ>?+I?+MEM z(a3rzlpCg^i+ij?rJ50F6T$WpdR0HGr=Z;#`Y;)2sw!4h#w@Yu8}DUel&b8afrw*e z!px6Z$yY`0<{nDGSgU8%2qQ7?6k0tb%^=&^A?tIxu|@V+M+U?JqZ$Zoj0S<1q-Eg- zwigg^Em>7ZD}2Sfp%;R>*XZshsZ70S>9_u7_llb4?{PEgky>}CG@5zuY9rHv5X+iTM0tk4%koq(-P|d$prFrvY(k zyw!1(H<8ov`m1a3aPa7`53ViR%AEfiPrvI}dRJN?6G$VL~ zvE{JdnVPGwod;y-iZt6w3#L5J2$CIcxZZzc2~AROv@v0ObqQ7`rVzFKAWVw|$3!a` zUrnwzgPGC zoR_dO9Iw!Gyf4{Lnu*%5U6mJ5{$Q9oWwWnU3}%h?R=c|^tw@cN+_8YQF}1nzSrOD$ ztM*6K85j4DgTcBrECnSk>xXg_LuOEh)P=p{Z%nzl^C?!c>r~KYM#y z+sB9dy`N0>Pwk)OgUN}4d)2i58oD|};gEexRU<`aG?j8|b+z=+a4i+9X-}Av34oju zR}3i-Yn{6DQ6;+I)b7W6G%Il=ha{8E6+LcE)e2}fLWQYCj7xDfLB_RsN+L(5-i%Q$ zlwjevot zD1!}!d)wt1KchuMU8UF(Wr*5Xn<_LV_kCe0gLH0K&)Fe8JNrt?6i5%RbIOE$432d5 zUmJ|4oW$LqT%6+AA8_1z%BK9qwB$R~QXV)iuA*nGFDY_I@j;p)r9+*U_V)b1pP*ki z%IBO2pO@(%{WAs>V_alg+O}Kf_uE^0seUVpXkou|h|z`KwdW9Aw@!q~kd|2bYxU!? zX7WN-P&+yc@zPxTMqg=~vxV}KLqHHz8)Ef^6Mr7BEu?u(nTn^3wmEfUQL=MNVq^dZ zD!5#B#RB%yfdLl;NR{68ZXly2Per|)$q80l2CF21JgWB6ne)EgXgX@L82py3RTtXK zt-C4fZe*}c?60ua5_oU@@-UNMsMag+^b4}mzm^SDd` zMTro?z+$aYB4Er{Z%@fryCiBtGQauFW%E+*Zmn1ol{8LV=+)`;4iC3c zR*Dp!iC9Vn)gjzo9M0t8bsf*FJO@>o4rqS94t%>hRntU&5zKVsV0-esIvwaQxk``# zF6&dQtQBxyTA7O77?sRCH?<0~c5j^?lUAH4FvYOg%}gHDQqc*;Q(-Q|5oKt^IO3Qi z`k~N+cvPw66k|m5m1*D{-CCn#e*-Ro`yF7n{thgbj@l@Z`Xvbw2N8m z>m?!HogD9TxuJ&M|bY{vtMbHZ7+Z8*(rWYUT?q3C}e&!?u-Ke!z;J`X9{@MheBe@?2r(& zAG6f7$BQXoug{{R6{v}04`%vdPrG!nhx0n+r8|Vu!_$&{fih*(i>d4*dra*H@?h1@n!ajpPTFx9&@iXkyB4QCxbC(uPu8| zgmUj4u3aKq_pbdc7T=8ni%{0Z2EFI9Hnkz$qq2_rJef?`JZ0swm6pT>T&Sy+g6k1T z|em!f7pQnI?0FYHG05UuvE zM}lqvK`C=viwwfL#Rb^YWIlHQTHTb~+p)}A7y@(hT>0>Uq1D@Pd`8X&N0Q)eEv~EF zS0$|sl(SX_`AGJA3iu(6Mye zDrt%jCXWbuc$zY#0|L^{G{`gBGdf$x$&-u?Z;d_PEqLt{x5croy~8&i?_OM4dE3g0 zM*s`XgYiR3e0&iU_3QaXW`ZsP;o%!^<+7$72@88+kIAcL+yi8$vRja$hVC6oJNn~a zsz%CJ?)9&(zx8*2Hl2C*pR?9Y=dN!odw-=~_BaiIDmr1^+y7->_u|RIR7_tkgFb`i z=fh-!J{$K?O=iDmo6elZ);Yv*+DO|pNGBD42{8}~oB^Wc8(^6d|MKe)WH zaryTB55Hx5%WR+ZIF#j($a%7-IZUoi5^|rsU=jo1*0qf*A5i1+dpB<0xc{L-9k1WG zf16{2JrafVE_0xAYr~#xRZ5Ip=$(;q6GH>ZA%8r{El*OvadCt->-FeMEmPSTWz2f2!%nv#{#Zr2L7PswQzgr4BVGrNo)+`G2X zV?OpRY$)ejd4J>1gS&eCY_hj~Op28xKzYRB(q(RguMd>k@eoBDo3BwGTd;Wg@Y2T| zQu7wsSWtB`eom>$cW|kWVT|Rz9!05rrT`OdQ*s5Fld{vh$ zH6h|)KsWV$*w$r<@heUgLC`nbgZpP3hu-D8H(-ln(Ci#ulXRQ=C%T%+tBS*dJq4*7Hx`lff`rF$%9p8P5e2Bt;zGTL0diE9=+p zpMjUI@L20-p9<@g12LDiR!8Xs%p=PSpw2j{W^mJ1Vue{syCd$v2bR#$&vTJ^04TLA zO+_;a|I6tX)0eA8%wWb#9QOADTjTzfTp z2yvPq^$*MfVAT?rBv;9F*t>(AINn8`XuE?ezLVU&A^6YFO7nd-peP+&&+r z4L`Y@NmdD|ua#z`!013y*^KOQwD}yF1rIlLj5&4gbdd+$Hv`3EERHy*v$OilG2|AK z!{;xmMmsdQyK(1-AD-L(J%pkGGEq$?HjbTiIJ_P!2~izhI%mv?vqT4=M~of|JxDI# zduKb#lCn4?$l3ntp#|J1RlT98@LF2%Vd|NxW8C}Vbf4%CS{;%`0kaN|-!U7*XVLP# zn-8wtg@f)R-U^@BPqPKn)dyzR-%ac>yC6m!WA(zEasD=w=C96GgTlD6RJ1Z~7L{@{ zXRbZdb?^BM$ISVEe{F$#@ArFO`uD!{@BO?PHqN&(W5U>ZbbORdoMQJJJtNIPZRZRT z3-fb|rrdx@@xNm0_n>a7$rvBrLs>1_nFxK!!h{qp6^X+S&7GCiscIiE4 zHg{Rj6*N4NuaK|OG4sgSmbP!*y0f+b=s>QB!2MS&kib%sATuI3puv(ewh+LKoa1E( zH|encAgFO`7My@^RvM>n}=&pjr+1a zwQ^1~TK~V0c9J4-PJ5_}Hfvs&;+!nBV3=P;@B)LZSPqx2R;=kJ zER$a1gjY0rEqn}7$?h*K38Y~l*;kg9R>M^Rck?L=%t+3bZ86Z`NdLasBh3Yw1a`N} zzT7R!v5Ujo2+z^x$}X3Qvh?HmLwbk7;hr0_Zp}T^tT+ZKCW6KSL`PQDn|bB!T`r%6znpO@jthaLiw-Qd*wQPl zMfT##savbyWPsD6;z+Qp z!~uigp)?OYn8~PBDK+@rGddhYn?(RL88T}~w9@(A(dqtp`h_X=0U2hrj>()n%%b*uw2`kY3Xt=cLk5f?Znl2HJ?6Bg?VlxF{CH0Txssf)^oC zAAQlT z!9|QlyteV%afPE8cJ}PnqvMgqD^ub4NEwtK9aD3_e;2vC*WP8ysj1Uc9DQ2FkDdW{ zz<-4@D%R;SNkU>nggw~IYp+dLNgP6d@?aTo#>*Q{hqpt0jk#dE1LA^_7E@ydiIc@b z$x!i@p{pG&F_-^1m^^b%o1X5G|6vY46{{lPl5w)goR=AO!hIyx zyizMuEVlAD+vzK2O}2bE+GhLNdlL$&#BEe;)bk^EQ|4vT$26IjXPP2{u6Hvz)nqX*RCov7DLi;XHYq z98Xc~CR?cqwvH~fp3oHWk@oVdD|F8GnC@`&)n|HgnX)gWw#v1hv4H539rxg&1-yp{ zhzLfrL&iPTkp%-Vj>cnJ=jCmeq-CZ^nKP8Lj}}y@ohWo?B7AH`46|uo1Ipiqg>%w- zeSiGob>$5^c;t$k(Upigl8kBd)>qO4^aiQZT2)VvFtNxRUH12+GFn8BgW*I-y*^5l z=-jy@;*c@_`4MKTybjZ~cVB<^692CZCF_{!TCtKEPyzNg+>0WU$jDk2yiAVBCkRPL z9u(@wQw?CJ_^3hzh}Ex7lkvt9XRX<-p>g?W?~OpJu4|RQmqx^Xi4?-yaH;x=D&f|u zhkG2MMjw&m2eJ-4WvRjS9bY?QXZ#UswZ=q1i`{d>2gmQj_B$c3 zA;$1Cj}Q|ZGS8d^aUtZ6yY-KU0ZoJ$n8^^WAG?_Ut68NxCaMf}JJj|kF{J>}53B$y zK&=c)o6SmGRI=?Q4N8M5=3)jWf_|qZs9v>dZ*<%*_xlr{yji4wYz)_r7J2c-|f+iW&tlqmTv3mvg4IRvCYxMFUotzcc{KyH#20 z%YOV!_08bST09)}89IY$tz-G31@WKv z?_9mpTjpYTT>=TL-6;?Gqo7uGN7%m@5_(SPvQlCNHK3Ee*;@pLJho|s+}jofD$!cI z#?srx^=&GW%DKpzx_)}=G!l9htE8_Pb(L1WZ;0?PYI>ros$ZjLBmuyhI#NcDa@UPY z#6BDeI5GtWODyhFT%bUWt38z0)aCJ*Jj=Vs+r6dBN7}#hQvyqRZJUH+E(RyE{-CG4 zsW=!BLLM-3L7^q5(D+4fY&D6|x_ao9fQ-X@+FLp}+&=pUD2}HZK_@1mK9D%o?bHdbPr!A(v~Nr2a?>f7#whijF4MuquC63tIpta4 zQI#!xBrNiaJlMu87kW2*!EOR_@ZaY%m{MDfVzi)JBSL;!xDJmL*f{l_*_aiETHOs} zMiGgXx!p*)sKD=;uAEW6)2GwT>B;U1N;YAsX$_Hd9}x*RU{AcPBus7Qvu-p=-G~gp zMw=Q=j0amic2kDfsf=B6J~SRPoN=iry)+J}XL$vwpl>&58d*zav9Vb5u@2n$co-bX zsR{__&C)kJ$P-L*KJCTdcpm}fJHSKQh*QvgWx4EmKV2*1ri!tpH}@W34Huj&4FosH;@7(l89 z3rEbBqytsS#2L5prczR~%^=)EIVaH8PnH{9#Ac~T7(PI}wCJ7UP#8Cg^be$k#(9C1 zh)GjLlUedZ?!6L}Y5>cPWE4^v1W>xhzRbg&$WkQKwol0$T(l6u)PUl359KCs1xUm;MMLxVf{ctA8OvR-tkZ^& z9ldyapiUYXrH422B{n>y@|g5rdwa|xh*bh-HvBp=kz)IlLq=OlU7#|SCIX7cUYuYF zExPOMa-?CBa{%g2P>aFf!Z@*O9v?*$S1md<1WtcUQkeU+BvA_lEQvi-Y7ywX@C^HZE(nB2)-FdnSZ*M9PLF0oP|HzFkdMziF3+^rnMx z+L0DX=e9!{4j-3c;gofeC{0x) zis`d}K=HOBPnvF@n{%|jX~HffO}sDICgOiS#!2mU$&#DN3~Fqn8ys6=Y;!Yf7FQ1| zUJt7WP1XE?rkbYJyZBH-wAs`#wQzc*%dVa)-4*J(Eg|7J=okR)$ur2Ua4@laU+xA1>8-D$P!3G9eu9?ZHZY1V45X505 z7zQN#Vf4XM&-~@^?RWFYEUmxER^>0JxAL6DKIL%z8@&0o`i*-aMnz!k9)aPj za%9I2CzA4WZo6_s#GLfdX=m?rhnre;yzZoTkI%iy#?k(JO5~f`aZ4iqI^9HDS13+; zqQiOWWd1#~+j`cyleFQWWeWFCK8j8}-pK~f%EkjCNm=O>5?hKvKiyB7h@H5@#(@hQ zN#VksYi>#B&{TuFN*09eT>=u#3=xH^g)(v**rJePilUb4_;X(^IJR(EtB5ejpfVb$ z)g4r{P^Q!|R5MU%cOurG{uS{c9ASf`2+7=&-qLGRE-bUaNed$kDm}D_wLV5p^tuabN9sU8MoAnIh(?P zROPw#J*Rk%DHY$093qjucWvpmlFP;w7o#Xge~gpQw{Mv++ z#1M`R;XwClJ`{ZoJg;5!r6DoaP!06KtzApwlLw;g!rnKwR)CpYM%Zr~cW>RkeCt|J zEN%eKH9G?C$8%AIOdHKWNFBr2J?zslY}3AVRYs~^ zUtI>1i7sX>5pRWJ)S{dk?O!anfk;jCi}`4wsDO=1E5xT+ToEMAPVdMs9~e*zEKasj zHP@;#_wHXM=}LhYdTUkU3bSRheb+_cJOx&*&Q)Tq?^wS{d!0{$$F4NH&td%nTWV`=$FeGh}l+``Nf&AU-GO ztLj|tPlD_7@xQ>%nFCA3L@e-q*<`4CT<_RlVopSSP*>bEtfLnG1b_3!urf{UhN->I zl4zqvRLO6u_IW zbV%74A9MlvvZ@wshIfO0oPTZ~p4^a@tK>$5N$nxo5|)b0R1G7cv*w5ci1UeIE==F-pVxP(E}|5ht~#?O=d%v2<v&v-; zHXT`Tj7gk)i#prE?@yt}>a70ebhvGtP>x3j%DZD?XSyc$dc_VpTnTTDSchdV7)`RV z(aw^~+l+jzO^XM*@*#zrzv*KtnJbWHmH>4##r*r$c&-hv9V7+DAI9B z#|Az0rEm_|qqM-KnZ!#&~IyhO6G1{g~`?+7Of_nrSMkyBck@X6}#! zm0SS9gPbQT!%|c0Lhmj+%g91PbWe4ZdWuQ@*e(>zuvr)!JXo%DuAqr_@dJq$^=I94 z)mljd0c}TTl-MsW;>e{E5fWpG3|mLN zy4kJV5e@iL-571CXy~PGvys3xA%haJBQ#>oQ{`5;U+AsKNHu$QyvL?7jBVF=KO?WD zPX>8ZN0mdD1nh$^y`Ge=c&7C zvaJ@<3o^UAGy4`iuu$U4^qQm;W|w9ovMT-1gc{<&o2(oUqGm0;P&Pd7!@>)aU&vi` zb%s#^+~JnB!)LCEl8SS>x>{s@FzPCqJ1l=?O6ZoyodN{CC_Nly-Wpyi9KoB2*3z5u zJVYN4@8O9&O6srT1*{2X#L?d23u%_6l4Kw??q0tCLGRA>-upN1_cpHGy+g!o@5;?P zx3ASDIe6QD+MrTVhj%MPF0Oc6E8*>WT}y>#)Rb|dfLD5NYJvMK%x{arqK7DR26&cXYN`2_fk5B)ZG8{Fu+_Hsf9&I-^~dkjUU9en zvgl)4jyv}mX-ysX{p;Yx;{e?Z(_K~pmsb|uYv`;bGNh@e>}wXY8LI1@0GO-ac*IaX z+Q&3zjU?>KHJY_f2A!x`(TLzMSp*bBw z_S^cL0`e?kPrDb|z;vrb8*8yL6ecr}6+;B;$#Kf9LiRR^DLB^pMs5pvG(a{6OvI!c zoyTr)G>6{P-dC(^;$F%3waSZHQBqC|Uay3i5K3j5X%XTaFe>Ym0uoh>&s0KGAY2Gp ztYtwve5CDZpd{aMJudixql~+B=eVdF;XC7}etFmJ=WyB1b=Ahq zHTuKA*<&01VBw$HqnIa9i*I%Ypp30dxnMKf+l_}Fe)H?|Y{&?U>94;|AkA;S-?jd- zcQ6O!T%z3HoGn+j2&3fN>p!IAS7%B_kj|U-`qz2A5zBD5sgLY-DFMhO%nupxf3!XZ z{@3hRfFkxaH8Pz^`BAjm#Tu% z-#@e$zg+WsRQU(%|1DL1%?Gt!X5#&SxBf38Vrd>REq3Xg@vt&2PWI^R{#cQDmZs?Zuh2wi0KInZ2J&3VXAFgY8|1w0hRbDDlWvaK&!@dVN0!;TJ!~M4A%4b^3>k zQc8T8x%SI+5B_g%2DVwc2I=gq5P5Hfu(KPtu8p{4<<{l%bl`r574*Y2U; zyy`n|#1Pm#wmqmpHf};)v3n=o%>-g2;X62qcT(C953uskgn8cM{1JyJP-Zw~fs!^3 zL%Pw?Pn50|LUP`wDsF49tIHI?qwEh{86#5RzJagO0Y*l?q^T$UFIg!RCpp~lj-gwT zBI1w~9HE0>`Gn$z0Ys<>EFwJ>dB!0c%Z#L<&Sqm#o?EH49omNDR7;$zMdyLCbA zI~V`>R@WFe$TM!W8s2qpZ@Q+zfb~mqTXH>djeD1ReU!8do zxMMvMQOnpNBrnE1c)9EqrSvDGr(2c>gR5({@f&UvipR8iaF?qTu3f%0`u>%BhC_$> zKk2J!P7tfbb&1zTfCV4Q+61MPvP^=R4|D4|B@{n zEmQiGnx-kxdkDiwudtbB-1BjVz1TKe%vIvK&$zr??nsHGlZf=L>w?l};2#&k!6j)T zw(Cf6Ut}IiM+D9qXHDuk%0VT;Rbrm}u4IFXB!pU7SP6L*I#*hZ$~Z~EA@%pGHG@ncNo0@hS?2Lq8=PQnmj!o6M}J6$hJ|gZ?th;jiE~^IBWpy zNP#)=Cr6C|2Pmjw7kF@{MK@ukgD4jIQ(_%JkzkCmnPQZXh% z;jj{k9XW`x+<(I!CFaxFjCf?)L>MW1)9SoufTDd7D>r!Yjs9v>{Y(v*NeQ44DJ{;R zzs7TUF=;x?V2C*jq)wLMOSjh zO@}_IKdvBvX-akA7XF;q@yIePqzGVu#tcbT#h9zD36J#?E?deHVGff&A=$zxbzqJ` zA)!cxrcPq+Xe@0x8chu$r;SazrW;&*o^IjEv+ul-K_*r<_Z+1pN%ykcWbHrgPPW5i z*xktZd;cW(6o$o)9~^2!?1wr) zJ|u(l@e6{rGeEu*6Tp%6fk-?W$wjx;0P~%=HXQ3Ez&baO00!7fQDPa&RL^j`Kvp_o z&GM#pA;iIw84~JxY$*0#D5VnnBPv!6hq1Ga4tW9b0ocws@j?p#vwzEGzF+(vklFjQ zbZlh2keNx!6h@|4e%f`UNsSIyv0G4zJK&T%k9L)NMJYH3nG4JYGXs!ZWgyIW#;&Y+ za)^WThHOBsHA(j2d$XX$=BxZ<4 zOE^i@CFlQ#EqW|xYTvq~vMtZ)iBXYKflBDEZ430;i{%|}>nsTYt4?=Y{+R43#tQTD zgG9}jhLAFK7{oT{BtW?Uwk(875;ic|oJ1Sksr!E``FmM&pb~tZrxe%U0h3y3;J!%F zEB7*NncI^x7mRMHj^J7}|6QJnds%}?eTe2`ksgO}-B~S#tA)_Kx3P%1xc8oVi~e2E zlcNQW&hTF_-S?DM$JoQ|g;YC<^I1WkPpTxTTs;`?lDCS$m>{erDoJ!CP4MN3n z1*U4;)FTn)lAeTF#@3Z zwK}26t?}^_2FyoTo`ur3Dz!ML**oaJZ`W|g#V|r%hXOshNzCfhE4wk?t~8bq4u&d? zTQ zBfzBiTU1DqV;Pz$0SwKIR^XbzzRb#}x-UA^0qc6MO+z6LN(V(ngBr@jep(s>LR1K< z&6ZZu9PX2@Zcm~Wv7!NO+gUVPuT7V$p~@q|nDuY#Mk;uk3)pfugakgxHuctY??mU@ z#6BKleRw>)XTjEo*g>I0UF02?Fg-WwnVKnAA zmSoX9V>*us!D90CiAKX?O>%e(6MhdTc+YksGpd%d7jy|2dodvn@!4bvFrKD-+*{)2 z-lx!Sse)q?jHt7t(_=`X`a&S~HF0}V~EGnp9BVm$K|LPPGkqm3121yNUlZHud zY1N{);x-qFG1JQ!dCXBGRR{h1Fn9?I4<&Xmy@=g!OPi&cOJ~ITZ}x}Ux*a^^q-byO z+Vr9VlLo|DqDvmIV{m+Y(d_a1iD=!T^s!Es>C9Z3kT1R7hP|U%nb)6K-x#%|*e9@m znv3t}UTW{zX6m2qTB~IQRW}YP1bKYvVMVGbX{?==%669(L|64U=bQ;8?3UJ)O!F zhLwtOalR{v)z@ep%Z6J_+(l)cUD;H$&1P&1E6D-wi8y%~{oZGp4vZjW$#sl=!eq5m zMo6no<>9i2Ywy1G&O62baxE&@>K9WN#YWY|L(nJouEikDBul_UQ;nviIU-gwBxf>L zMWe`Sp1kdbRk)&?=~D3aX6(0PM?)#g2r9yXrMZcNCsv?|UZ~;BiR3`WB+8Y(=RPDF z1ZJ@{E-==+AfZ$UPbtoF|C3XW>gceG?Ul=b-Q7~A5xJb?w~S1wGMgrbi14So1SQv-mh9Ap z&uH=`5Xmn4b6AY>kU7JNl7(z$@O+My%IsIkrU5hX%`8i7;qq1D&t>IeMaZ00^e_qa z)`;Tb?BfZB)5E1~Mv=5?DaQL*lF z)@~P}0T{gqsmiGVVd3mN{6bi;M%z!`W^*Kv7uC%9uf4eLzEN9!)|;5tGv^1%+~^dO z(St8FsCBPgu~}^Cq(M&D;o1(ZVG)&`P8WLe2{#JE3*&J0&orx)qDNfe(8Zk5PFW@V zfwCf$q3FvIpYf2KDNgE#gH%JJMQ2v~uMfHKU58hbNDY3Aww!lRD(%dp_)c1x{jdc1 z#UR*l-&Tr~mg`DB#sluW)}%F?fE2x)9OMLA+;KHM-8~sAU4#0W?g@Yf$4xk3ahSH%q}^%K@a=!HxI}h#$KT9usj|d+hdjqE^_u7w6c`P3tJz^I|`;aGg}WV8d8jvy;6$E0sv;K&6ieJ7rnTj+^(y5_}cX2 zj}FX_sVi4JErX3Qw*)A{^XSmFqg+)&Yq2K^a#QN?!jl=MvO=WSuw(++R5PTj)aUsw zfkp6gffW(l`%Qr)bzL|c2i0B^6^!P*}Bd}&6ZzDKDUhWx_XZR)_3cF?X%=k&b6 z)H!$os=?j`*X$uQR`A!Mv8Jv|;TY}ij7|^oUiSj%b4sqgrBo!*B|8C`dgjv1ej&*` zu+vx^H_eMF8MopY8`np>Yj4dFZa*L;#xYj3GS^r%NSqgryt0~lNrHrQGCcC(>(3>= zT)%2C#H&FrDc==>f4nQ=B*f6}{{E?p)wsOH-#Q{DCp(~YAy=<=73&3oMz){Ri){ec6b;g>-=q#CZ7534Rd)211cZE`EP0OA%$b5~&&NtP zSEnZV#EMGgCKS{-cLZkKLD)L%H1qah1rw-RjaFAy?2f0SC%Y?z zxh+$Eh5SCt@85lYdHvdl%R8pREx-MZ<>%jccl7Q%B@;=n*Mz$DcefSb=H;6J>U83P zH2bCwek~%u*oGnQ;%gF37Wmb4%BH>mK0Y})0!jNl+&tbLAMA~}hLrRgtKWF*?XR~j zIUfWas?PSsC4$D4ILk?jwN;%$*4&i#T)It%-XB_5P|@)4_|ZzL{#{MGwM?JiRUg*6 zL?YHt1E_`gM?cb9^rIia4Df`>Ru6L*U-X{7mH6=T-5b8B-Qek^>S=+%v=GOdxY1hX z^-Bd&Iq%QfK z&tqgioeddW?Z4X4+}R14qSWBgQpTbCdvgGBn1Eb`;E{ zl<|RpAXN65LGl5K_1_y&(6z66{<|A>oJt7^qi}r!BRe>fl~bwuQCO2@mHfQg{}lo7 zHUTNRp3O7|WH=8b6l3Q8(LkFf&;8Z2zZ(Myrpi8_b+K?UkfD7azLQtjEuH9wmMIH*O>*;!{X8u3+-Yz!I>`W7D z^>_y}8n?@>LOXB$|_dTRV-2L zPA8Mh20;*Gfkk?e-3$UO66_AL$VGr82yzu5mjM>Y#RS+al5Bo}1#%N02!iA?&-4DA zpYQvMEb7PB^pdb!iyc=m%EAW>Gw3-6H!7hFQ za55SmYm8yBn?WIzdqmiZVC$hCHo*Vsp99XJF{w0Vn_lfGpMoX`Z4D3R_L*6aY3H5I zP`(>O2pJq9`Rs0QOx0OakNcczq~YYe3A|VzpRiNa677!1%5VZ}WRV+E9=8sQd?t|qJ81SLP+|X` zP}(YtfkMkx39%!d=2Y0n%quI+c98SYgnCv-!)JkJmcg>R`B;sV)Sk9TT2Dq3l4E2Q zL4bsY8?DX>v*=_AQ3@2vEao~NHOh3ea>SQEc#{%@i{O8D7)9fT-r?3$5TycG8HXh+1hOp%C~sw!qym~PoW zPwG)PliU<=IH5qlIQ3{*HE`2QR6hc1FvnYQV8@?gicGZ>$sZh(90vu<>Z%r%t59N3 zl#aYMT=Q#KV6vKTJg z15_3-B=?MQ_`L_0Bq3%{ohe14O9o9=+eCYJo!Z&k2f`@XeJHVROrk&maHzAJEor(3 ztYBe|C4nz}5xE;gBHNO%AAEOn%6=%MA-G43WC$GdH5F?i+!Slrk38$4(jXCdfQeK# z@Q--K3R>E-a#tAXGF;KgGbC4~a2n6+5unrx>vf`Ypye1Itce`a-t8;I(dh!kuHVO9d-N;8Fi$@CU7D#yNLzCsrXg zJ5DoS&S_{(;!x;^75Jg0pnR~nzP7yf9v1_AO0+B+aB=NJ8$uHWXb4SDf6k2BV|Ckx z4vQ@n`@Sq**m>wv;wFdeZDeP7x?)eaobc??KM?dInnp@^b8S&bkz-8etjn1l7xy9omSS{V#ZF6w3QwY`tmKEfl=71HB1)HtY**a(nPwr z32Ndbv?-RQn`EDQAwU^NCqI1Bvwqd%4Jaj zo`7Or@%R}vLt{Y(e^jh7jRWh!=v)OYJt;gwKI&e#n-2Py0{NAQr4wL~CA zJbIMZ2Q-cH^>kYWd?W;n(BM$AJsP39^c0UK4=oOR>;(^3S=F8busFI8u}DCUdw@S- z8-%SOY*e5@?O^0}dkQ9C$GgVv9ojLTv8IKT_|Uyw{sH;A_vDxjg_GFq_)~hp4B$;l!`&d4w2zUT~V%l9DS*9s-)QMCn8bap*5Q zHUel>%ngAvWj#rT#m|cy(|~bbHz@9hu_kbu7&$Y?M-7|F(fD(vh=htq!}tcU8Rl&O z%y)Un3k_;73MHPo@BtybHF-EYe99?whT1o2QJ9)xqBP1Qlr!NGC*ca9H*MmDnHU1d zr)*krURR0_MmT{o*kmvtk4StGoyzMJuzTYt0h}m!B!EQ`WG`PLj$S!UCSQTR7(Pef zxR84$q0n%__BGyh+TaY~fk=;6b$I01XqLFM1T;`2FZlkq3znGRdk_|szU%IK{zUFA z{Ew+nLS_S1XFnv+nj*E5N(d1Em4ajM4?xb7Vw}1Bsm)_vdXP-BJ_EvTvEr58j@(qLu{}uQaNOVOD4*t!R z>-hQ>zlKPFR&--!0YzWQqd!>LUs+j0*_YFB3|8{jBw+g2@>b&0Y89TWe1fKztpc1( z?fYjd|F#U5`6yf2&sP3Dl>G`SOPnA3`tPs&eSG~@ewFA#_W93N{$qT83->8Pl*BjQ zivE+8|2!)qy|<$Oa^)Yhv+!ilKL3-|FI~d--weIESFDz={_>^Ozsw46Wv>UUu(-7P z4hw&$(mFmFvZ}v-Y4xwM>X*%VHi3F|^U`WJD~n*S?q6CxX4%(kDS>r3?u(^`Elzt46F6er`4X*GsEkeUt6;8dm!CH&+*=G&eX}=^wtidY`4gQ8s{C z`P!SSAF}+bsvo6B7pt-L=IUpx@#`f5WySy6o2&m7iYIl5FM-|5$Sog}b0B}$4zD#M z*2&)~zR8DaOD~0GypWGIYa!piQeHv%8c;&FJ^w}_(gNpK*GH@7hg800r%%3Aj=6lT zKgQOebWr7M-8qqh(~p2ui6=IhX#AMWw1US9Q5iesYb{o@WHKd+|Iz0^`+6GQpZW-t zkb^_S_x~UM(v&aPX~>~$5iIwJ&$Jur5%Lfk`I%7%5ve*b`HLx#okA2J zHRkjV$8>9xlb0XJgZ?O>*Z0)$Q6b(Qo$v*IT$^g!tyoA$62ji%e^LjP(2K2PeJ@sc zb}zo}_1$=BxgSwrqVi%(Wrov4YjN#E)^>M7iPYB#%PG4n8$_xJ^$Y%RwsSAMv36VY zf}2|Hg&X=gC5T@yp`{8LE5EbyEy_RntgLK)<=ZBHRLX?|Rl8L7Glk25|NKVz41)Fi zzh9cddcJ?bdM;ScYsh+pWoTxVP5dr&wJ8Uef8IszlijX-3`AjU*RM*g{q-_PY!4Yy zz$B1VrAh1I31UWBBWl3%3L92NcG$c+Iog~5-c>bzWIUmI=<$l0?Tz%;fhN(&BMsHN zk2srd>tKxB1l`u|aEJfEQeosziK54xy&^6PmPuTq5n>h=#_eMnSL%OEvm)ce^y#r6 z*Cn_M!o5DBOu@I_G30=g9xVjem-ItZymk?<3c-L5=^(<}7cOg)7jCw8r>>4xe5LEt zM5v4eobm)iu@dHA4a;u!jNe-MI!N+g5@az-{M##knV)2N?9=aw)#FR7WnZqWTt%fX zv66k6W9~Z9AJajEc3U<1-TT!7?NJL12L3UrA>N?qU+(u{H{N9!)=3xC{KwyzO3l}C z7x8`vw}#6Dq?NdWoTPGn4HE)l{2?GAeL=c3o$ejM)w=tG;$%1x@8A*gD00IkpqSoA z+`uIb3<|xy6Lf=5nv|Q?IT*2#MAVF!@2x#5-s=t!ueD!1L=N=c4ni19o&?`e@=l24EvrfW#PssSze_ z#)1ni>t`M(DEA)(z=RIv&P5}v;ZhF%E7vg+eV{*B-hBVTqs@Z1{_qJ{UtHV# z@CV`6nYrI(QV@vyJ(_0z)1Ewk-ZoFx~>dKd=X1$H&L5{lP?@Tw(8-A7gyuhlED6 zY)OJuyz>h>1MUZpdY%61xxHXG-G|xN)e3b184Vduh@S!F2lD0_^D31U4>6criXrI} zC3hgZZgKE~2P^1v(++f!9rQNl{sAkO-&ewLcjqMN!ld}h4xs_H#1bays^Cc z=>F#7+R}qZ8|_CA?>|_)y8)#P*VI5*{9ey_hi+6~_#t2+dc@+QTOnx;2$8SRn;gmn=ey zkn|IJYKV$tQ6W`0O7HdXik%(d4T1$DqYse9bCA*431(Zlk>htP7KI(@AXbr>khSXv z38L{S8-C`-05->J2#j*SUE}`A?h^qrwF`7$7ue||bfzii=*j`r8-H2Gq%mki@Vzh` z<0Bm2W|AyOhzi_ZiW3xsS00YXh}a;G6?WYzQzqOXVj#YFv4qPoSXU5TnPgVwKbG%I zM(Ftni^tR0+GsDYKDfKo1b}^hP|zUsF-u62T^;2+kMYSczz-`Z5v_Hq;oNQ}(NYm?7CvTi$96_RGY5p__15EBiHvhzi0K z_!qq&`0p5JL{FFM?Fyy<$OH=H9=2D}tRaBeeAq`;yTutgiqjX4VPwq$Vr?k1Mx7vt z?@cWR5rCIVzxN4uo)6-ZR)G{Ku=K#$Mo7DKJ;VA7hi$ggX`wID44W~@iT3Ri5XjXN zpe?~(2m5+T-9LaK=th&nqwMU$Vevf##mDoqN3vcXUhq+fX{HQyeBzScmd;#wQMk#?FpIPYsp&r4HfTO0#E#mN7o@lvAId3{kQ$vV zs0Kn0m{4cQDj+`Dm|)4aHdqyCl{lm7pJyu{ovip$!yGGoId2!`cn1cYE$oW|hoDq& zts=#Oa};c5hDv~==<~Gd!W*)LX9#2oEVc1SC+O=zCnU=DTs}Kw)R$~NRvQ8v z%U_tH0GsQ;s3$5(8T3*VpGv-nfPY+aDs>{Iw+p&rQshTN zmx*k$Dc?E&xDlt3Z+T<38hYQMWGVxk6C><(l)I5D`1;KS9 zQPoA0;z_V|JA$dL+uDcz-{^b-FJX;Hp_RnZhHvID5N84rKfo>`YLETZq5L zSGf-Mg8z~fL7kY4+b*Flm>lYV%eXd>pBZX9C;5?4Sz3n{8D1GMR`((ITH;Od6p2KS z9mWSkSo%^QAbAJ1TIraG(S6q4fvfmSI7cdx5-rHOs#2*8E#oFArj2UP2PdG%QKn*M zRXrX6yo%XLw{dymIdS}plq+EpdU1Wyj18|Bwfhry1{++rGjyoZUU;Mzlr`|9BZPd4 zRBfF}ZjxPsSq}SSK|YwI;owj_`S;<&`*YYO9Er2FhkTB=L%2M!a!t&W&>KXCj?0m3 zQMr#24x}q~<^aC5rSAQ6Lcbgd>_|YzuG>YWGgU$*{gaGPD~ktPJ8MlLIq6I&xmj%o zE_RczNK!SfpH^1zC~jxC7A0{TBDRB+l-HG+SPu?KrM(weYyVT)+7N;+u2JWd%ufnX z8HVNRQHe+3j?{=}pa#u_+rUki`B$ds$al1ObSF`vl{KD4nH0hVd2*`cI8%=*Ep2`J z8kirZE?P=<0`b0UZ(W^Q|Gd{gAv|*pbOy9dO+Pn4E2~D1V~Elt<0B&U)rM0+Hd{u; zZJ4i+b^$Mtn$rwRRCOK0U~wBcEryv+O!>-9!}4yhN@DV-9)fVKV3cAzbb!T9{L+@* z5eI}p5WRY4QbU;!5#SeP(J`{M;g4721}qn6%kV8z2DQZJEd^CDV}bu|-*$=sgb z$o!+h#_G0Ue?V5IniHQ}h;A#&ruB);2a5YL9QQNSXH*m+vp#l`dH`AOg&% z6n*H^)mVSD#s|cWhybi=SOO9Q%RlQj8`>GX{ipC@HsciymWDS<%(JDpPYZR|5js)U zZ}W6hZ^U3+J@&(^d_}lXlf_1xSY-N+~;1ZRH_~e!WBltZ-vx6NQ%}GqUd=tPJq|*W&lF75sGNkJ(#^ z#985=to%DDd@D0lSkd2H`HxWapPo)*|Z|T~|w<+^u*`(yy15cl~vI}px`urQed*SMH;pzir>Mw$; z4?QbLN!=sF|8{2&b8M*fH1RfezuYz<$D1auB)BMW?;+u(<`u%Zr!5g3a(q3X%?BlarH=IYd&~AwQ1`BbeM=&f1Kv#gVp;Y zV42zO3g(S(MMa92V06HxGJ*CgW@m#hmmFe8t zK+^hx!wS?oI*oRv7Ao0C5kzcbVX|79G)Y8Eu9SEYP{gF9h@%gKk;v-bNkchE#cbKo zBKtdz$38QAFsr7knpcgBihA*nypk_4s`#&Yg>0!&EB_nQa_Z0;43FXd6kbP|?+nE< zT@5)g+!yo`H;F3)tYbC)q*bv~u`2$^E5%(yrT9mv1fgAbD3{4)04+c}{Ux-iM)c9@ ziI(@l;_@cdL8wK!c|6g~I7z0_Mf?dqfQQn49R^bM^ALPVFa<~M{&1h(jfgJ6#Nzqw z2lWSYZ$u6pOU4^I)5FSjvzt^KPR-DkBnPAiorF2+g-@uM+<_$hIJCDxwZ!uihs`bI zP{j@c1TxJifNSTmwYLqUyNQ8gVTT-yP|ol6QB+=>8T%8Sb@UAqXLwhGS(`ss3ap_z zUe2>Z>;iNX$+vr;O2~90iy6J?wXIqcL__s~bBtj%ET9@D4&q$-Jw;dU6mr(U7tQ+l zjA=wzi$9obSeEdS1^(4mQp%{_JMkCu6UWJsW?j-H@p2LGxoOo*5+zY7x6LPel-n?| znS?$i9(DjDhKY?WVFqu@v#oYJsmDvb#5zs*(;YS2gRDwu9cKi8+0N)hCmPon9q42n zQt=y6?`>=z(arL%h3+*OIi^+0cg?27a0f1oI>PMlK88YWyBKpiE!M zfLGAJN>ws??lrTIr3R5&d+qq8wknxdUX@=;RWs78gl&x_VA%Y%c{JAV{4}{j|AViQ~#${|?)$#K|l9{S7zKsHYYM zNS}}RRXRD92I^4(>1Z~v3KDQgJ0Kg-jQ09>q&w2YDpfdG;CgWuVg8(H3A!@T5qp7r z^lNOvqjIx+`yP6lV5SZVSGly6$rUO$*0vJVNDXP2Ty~M0Y(ne;rb{5PV}pF>s@UOY z6aMI~rmbGvosB@o-HqQ$I~)t9%Qut=9TQ-xcG)D-RxXg@OCrLE8TV8HMsLZ|V;s;a z-}-gA3{H0V?Au`3GjjpSC8(drdE@!us!hM%A$;|2e-fQamd1%1-*$YOoX5}L{uhoL zhN63+4j0ZvzBe@kHSVP2z>!`ML1NU&%cPU;Q926U#W5c-mI6_N8z-kBB_fQ1!y56H zqufovRPfJ*9;L-&4>?*aXO~n^RH6IE%QOYy59`=BTy}v>ni$DhIl^_uwqbQWt7hb!_ujDo`kUmSK$k*A=_m3>8bDtiKm^8(sJY{12?Kq5I;{gpcU5) zV~F9XrK=iGTLq2pEUw*Ix{vFM(9S;KrTR_Ud9D#A#gWNi!4eT-y>m_Vjf<>WyY586kY|@R;`_pgm z{#5SM^3AP5rG`9kjc1;uQ)C4ayD;a>znn-}S_DwQlI0O5iPUru+JGE}n_Iu)bp(#g zE({#nDLGX%ptkM?nAS-QL&D1ZK^R~}9=%=gb?H(2F(jfsXq!LK!t2X}64t;L;{90` zpbP+riFk{KIojneR56*qz|`Gp;0+oyB&Ovp5v*hd376Va(NAJ1jaEL^;EzKB&%mnrxE_=3%T~><=3t$UbvHFHZQN#P??8*Xs&X^FV!*G%$m%i|FHUJ)n2mA zSxX)adlk|Olwl~Mwngiy88TZd@U+k@_;ExB{*o(4m|;p1JUUJt^T?*x zPZRoiiQ{^pF!#jKfit$#ojPk zur&SBH<`G6tKR}Cs#{*mdRJ1YfuK(dLPr19kh<9fZ zE-vC!NP=BFSpJ2^sW2jG%=eV1{JaC5XAoU@=i=?5N4P**5xh0f7zsZa!z~jLQ$&!j z#J*6cak%)vdkS$95PSd`so^cBffUG<{om6lG8UXjGjLNXOlZ^ zeJqbw=+Lc(W4zbdL?4p-4(&r!ewZGTH)|7wyN!g9Hf~M9F z?;91pW30#n8WfIuW2C9m7!kHn)Y2xFc?>N~aU+!M-mU^{&i*%o_lWOmLLi&EF=qdu zAv_=g@^?fo&Jx9!-L{Y0yhbqUr7AFET6AReK2%6B?QUd$?xbS$wWYT#`=g83n~ zAb!2|QMED~L|LKHe0w~n!MyicZQ1=cBK))QJ0C^8nvML&7RAm662wxt^4I0E2jhh; z?cgII&3A6zjG7z!u=abEdBnFgUQ`iKdd=roS*$#vOmV#3x>EJSIQWz zX*`|zfiZq9V~k2Oz!d+Be+s6EykLhXqu%~w>yi_X~Us#)w`d+N~So$8c)8;e7W7<1@g?3FP^*vnH~T z*t*G^Ka3%q1*%OCSNHox>j}t~q>rFI2fsKOdXC}U?9O^e)3!YeV@ z7?K9l{e%J05k(JC)0q7ZFyPIOgl2&~4>JOzz~hVU3Boa576)VD$8R4(4U^{>mggyi znUX1KjxurRP}Zl8_V!W^e)W>#0xvq?KEq50p|?@@rxQf<38`q3HO7@3t`o2#79K+8 z!6gf8^ES+dup#br7%vJX-fgkA^rQ8~m~w|=%Ro|a%Hutsp88M2#VuJ#A5a%fg@};6 zkAsIL)_Fz{g;}G*06t-O?jq3}`+b09!Uyt1brIf1M4^2NJZH%^@VZ`BK&ReP4lY;* z2|%ZhoiSNJQmbLNY5ISD0nl2)Jy8Tc2C{KUkiYBK9`9l#g4PCbWw5{eK)+)-5Q|1j z5T>o~aEu=_$g5i)1&9&p6m^`%%UTp)2!9$|5NP!X)TJLKuz$4$#6-!`;BEZxkcZ(qiee*}u`o!&=`sZAr% z>taF7D^Cp*4x9jv+Pg-5&V@h+M-fSy$Zi5F9SJ^D@0c7+Rz<?IEdom->o5l@?NF z;Hc4*l$p=qK&w@}R6)^h%Px={MJ zfhe!~9i!JyVOSUct5gNcAlIrAn{`6BWso^=8t`1yLR3ix;}DSi#?k?4Tf;2LsncUJ zTE=^&OPGZENDGimwzS-wf?e-fn_MR#7wQcr_LiQtnQe;M*HW?`nYid9Og2S0f(7!) zIBdJV;ZJif1(0ytYQT=5W2SJ=72hfvVCvCTF6j|>6cU&%`6PpA&>%AhNA2NC@&51_ zet^KKF*vHRaZV@jS1MEZ+s;Xx95PFF|1h1D)5`@28-Y|NPOVSqpID;0O~7gGuumj0 zRfoD@c->j|Hec6LMW_eR459%T~zKYDpXwQ1YrhS!GLidW)IKkHOXZ1PLUYvYhmYx&)Kjd&BhWJKP5D8!#Pmz zJrJfItZCeB>v4j&5UxS^HkbXGK3VG4o~)7_G1lXgaTD3ZAU!TL@SjFP-2zpJOkMm@ z#fOb}$M8J}*C_92HQ}NWv(fE>SqC|UWt&S}9|bg}YN!X2Cz;FjtH@IX2KnR(jW|@3 zBFY~SDJTo-(d`PQ#P?_cN_v(q+;=LH$~Y6O8wFOvJ~@EAj3=O2V>G)V60{X-j}}ga z-N^@NAR=x9o<;x;#0lae2#V%NzK%?(mI4eLt&?%UO?p&EPz;$Tgx@)!r?|P1BOWSd zh*|TxjlWXnpP#o;1sV)IYT1WK6WI$Kc(2aSzdc@%OR}rDCTpS#B)#+MFtR9;cJamw zpP3U7Tl}Q18!wBU#rgt=_t7J^k|)&m5=ygv!dL4ly@#s1Utgz|^B4;Ymm-@w-P09% zhGa&xE(gP}++~J1w9iiJ0F#0gCi$TIjh1qQ-x`nmpolP~*7X3@K*~_*YG^lNn;lT^ zQO$B-BSWbS%`Hk=#O-A@I7|(WPVFevD0LRT*K~-N#?{FfVA76Hk%>PMHvgOv8Q_}{ z7C12-F`gaLeHsBH)!>`v(Ey<+^jkt^@NfvLqkKB8g1cNQCLqx`XCycC^V&9?Sp~po z4hPW`w-JB>kCGvtSmtG=Ia)7}2BkO|Y}!jC3>e-9E(2oPvMj6iUg{{2j7JO+UDl6) zV&X@`$q_8Ka&JTYM9^+zh-6-S&x6}jAqx~nlqF=CRPx(DQDt@1ooDXu1CgglY7m#X zKcVd^E+MoZyc`HrPylzSEwX!%pQ@PfsziiS!~?F0u`(RNgipsEHXeDOn=i8=-#e=& z2_u{a#Bm_oFzF$GH*;oR3prvdPSTn>067pJXx?#iE0K5IFbJ(`RL z8n~1A5T_Us*y^AcNKQfWi8b?AC0p~iJeDk#+-#yqhDtp!oFD{UHZNa@tb4V;|)C{Is-^AcA)f10=TN0gszWOr9@K=AO%Ed z>|_u&gg8TxQ%Fesf9$BxQ0Pllw#q$xls8h~&TO>hy(iZbwnfIh?JotaI%@1-t6^jM zj!_Z+1Q9;kpsR3tApL}mNS+VIO+&OoK3Egt=na&R1QE>}Wn0Gnl*olvvl2@0k4e87 zmrkE^g>E2GF+;=P=nyoW$^*bL5FpZ7`8kQC1AZpOi!9bC+ozuiik(U4!U#^^`kldkLfiP~gclI? z#Er!z!WLR&3mqw&G&w(2+Z0huV*$q@C{&c`mk_oK`o*h*spg-V=~r0lh+&C@!_t;) zD7}RZQ=q%*)^l@!@cr(f84Bl$9~QS_U#wE@50_!%$)T8J(_U}gwr*csgcFE~k?9#J z32&@(DnSZUItL-@4{`I-l@*girA%0$a088rXhe4UQurM_jhp3(eo~Y~iSzG%PJNQeZaSq8@!k5=OmDYJBgY^6q&pUVp z1do(5b}#4HXr3OM#74}``gu}32kYlc@WQB0@Aly5aLg!%k={8Osi%0}phWTLj6=4p zx2Du1k-;s`u@J?)(8u{HV5Yz(VxNyFPM!(~j5m7eDBs}Bz)QKgON2vH-F4{2K*R1X z-cug&|6+aFYDi(@Bi!`XjVh%UMYcq>L-zs0ri@^aPaVVCpD~Qa&4ebaCy0u8-F$p4 zrw&)@$8Q&3TtIdbau)OOg*%mbc%|pj+`Vlugk#h4j>mOk+C)Xq!8VDlanI-Y6%#1Xk7~*Sc2)IU=nO)NegSuXGA`a4 z_51L0Vm=YQ>&2beRr6=M%4ftOuz=3c@e>!6Ck!xvYZF{Yi`y;V<(QMT_04-y>6Ko0 zaE8OvQMr&yy}HG*$zSqFJKB=C$dDT%Er_HAOn(NOJSGPBabEh--R~K!B?QEAfE$ef z`~1Z6T|9A;&ji$c~_RM|-`a)8HZ}`g-1bntHPY`ez$rnxXoX&y6@O4~Qos=TA zb6kVS`W#({*1~PI?|OF2dvkX}b^t2~^d8^wL4R~FOr_c4PUdZ{i<1((X8n>{QAK@E zY7pt1m}Dc$rEerzG>e)|$bElNQE~VKW)lSyasc%i$#xfC@!TIieITjG)UEkQ`LaPs z86U(9PO`wBxho0iwJl_cgW0Iv4w zc#6l}JrzlTq|&Q_L-YBkjfgdf?XwmCGVjJbst%7?>1V1#)|oA@#=&3*z*E2s%vHejzh(y08_c|{r%7~neB`tz zhd^Ci_J$y8Jo{#5v!|>J#fCkfwAVCryj4cRmnA_4$l`rRWs#Mr91R3RH^qK;k3cqRTTQ6;s*0DyoDOw_fYyHM>Qm(tR16Tmi}^bQXdE`_JsPXvTZc*daHunWXsR#gxXL6832 z2#dz2+2mmAx+&<=8P8kF42M=1pk`cSavw+sSOLce6{^U?MX(~HlP$ISkP9Gv%hUG# zVR3JHePa{SMtEKwWFuT_B37kHHX@OPm)ZWrO5c%7uZD?aiZ$n8DrN(ZtV{sRQ7F9R z^My!}pn3+{)3HB8R|7R4E5!zjSPdkFP{DUbr=n>UJ;SNYFw|El;+DLVIUh6;5^EQG zix?Wlmy;34m5nm}!N1b#E?_qKVo^^~^3AjvK~ZWlBRuJ7A__WIC4K&?7#JlsRufa+ z@o+>{5rG27kHM@==oLUr-`KmINO}Y~a}yUgBvj#ZNjd0QsjAI{gJ^pUClPS(8D_~tv?-vp0neDk~d z&+mT|qfR9yccI9L2?bru?~G0)hjbV)Kf7V(w$bxo1KuRgy$o~SM`?#L)?H;o3C)Xu z_JOZQhEi2$+HaMx4@Vs5vDNAkKdV0>o;sDczBY;-vGCJQtO~ zMTy52kZHm~&}T?)oMKNVfoIy1{!0RzxP(CgAyxaOu|Oaoi9mJ?8w|p&j;tr`bp%7; zQv`#~sln@Z=C2gWg*Z*FtxT^%e(*Sy@91#@4@wJ@fUlS=fgiz!w4I-q2jU<*c#O#} zPIC0jk;XhmdZQZp68eGW!zzdsK^Y=+BhAta?m!YqWH?l$D6ciGYG8taN+pEiCDR%X z6R3>8;!TN>R4{H?{1{~D$B4<{n-&%~UGec_!eP$aoQ^Fhgo#0o0cK~Y7}py z(%YzZWITthGG?`ZW;du&>4vScZV+Q=XVjB?T4zADkGPKG%2K86(^*Os1R!t)JJX43 zC0nn?^+xL_!`{FqY#jt(LpzD`P@?ftnM7WGNn8f?fX6c}<*!7hl%8{;QU{~xc$!ox zbcB0VrY&ydCD{jV6F_FVnn_UrJL8t41Be(2H^{K z-zSiYqZp_nlnjt}3W;5(UUkEAAs#-vaKR`wgTk>5)o2hNnIi}dZi3`q0+Zd^%IhOo zC!<<0;0~BKB9!m=M4O(w{u;f@6H!yIOK0JmV zmJs?jT}fEa*Px*)j!@Nnzz8g_TR=(hzZeylA{%1*NjJg-p{$vbGw)~;$APzH4Fk6Bb@B^!0)-Z3Q72?8DY9#uo z`HbP}^k$Sjw1xQDlLKnqxBGX>S}e>YS&l#@UM61|z?Ux$EMq%-4BY{{Q1 zvOOqeT zN67~W_?eZ2#vHu9F-r_pJZMu2Y2wo=_;l*o=l)489>knLY&Eob^;FCEurSF+8dTN& z46~A^QS8d5UKQxMRHOpOozVa+4vGHUh^{cd4SMM5lJwxo6);x=gdqddR)y(K86N|u zkh@cKc6M;p0y0E@NBzXs!7w3Vf7DaO8Ir&(_05cD)~Yz`KxFKo%FU^AP?bV?FC=MS z+Kk^-iuhNG@uuB^kFRUY4rvGYEQG2B0_8q(Qfge)FmnQ^SwKCa-|PYZ)b1Ig(A_Q` zGFB(J42L-y9^wh?({5h_6~Yb*wlC3Gxn=fv*<%#4$vtBnI2Oli*;Yq6tK&`}StkR?3L3#C8*cr{UTqx~uXIcUy{2t?x__acppe zOM0?Yp?|!wwtFmpius;i#p1EuONz@Ch+C zvmV~k$|780tW_C|p;ocPI3c(V<5FS$sIEIMYrY$4Bvls*kKfwlISt`jc}&fv)h{-{ zY-4oMCPRaD!3K%<{j)G61zxo33p9Frd^B(W}-_9 z=IP+w(GC@?t8b65azWjP6_5cj@PV`rJ_b7oECzEm)Y}A%Abf4WP>m4EjLgmP#|7Lh zl!eX-Tg8qo6du~1 z%Pl$e(Zx$>;!+N3B8XYQ)Vw{fOE5Q)_-s7{TBCm@Xt~9BK!UK@P7vvMKoKJks@?SF zaLxhjH8eD=J+^V1<^j;p2{PUYB@3bj$(qLpm(>+1i0Go#+l((K5YV5vm3)+Sw|+{s z(yx_jEi4D)&3d@qtJkjP;dbM4xj_V?lLk8vZuq#RZYHpND;*K12lurLmhkZqDY0S4 z!7?91uL^uz1NEv46Ze*KLbDNxI!~PMfNMO830Z_*Gog?;Lb4tAwjm~}XF2xlaEQ2R z9a(Qlfh_CmJVaw}tHi_Qu3&ImGO|QGW~HV{jNRQf1Kdj(ccgY$I4#zD(~pH9xi6*9 zttHBmFkN~J!EXwFV56>vUe*cE5LTEgXcn7<;RnQ$Fv2)s8a7xkg0rb3i4V=Vne9Xf zL+mz2QT`=oXBvq3yrH-g$GMjfhCAsE8!~GM?w1mN8$;uiN(|1|B&KGv7?qIQ6dkcb ze*T{?-1ZBG+RhGf<>-|Toy*mB=EN1u&r!&?5R)sE4jg8yfx6STI~&b2a|*1{^}iy9Zw{w2W603 z@Acl*R{)(s2j;Zh4kXnBkaWtdP!%9(@M#fAB&abnuHCwcsMPuZ$a4vI`iOlCS5a8$ z=adZRPyu@0sg_9Yw{lSDifhHK);mJdl6ANNNd{3_MePtMxDu6lhl$=1+p$3J8ggz} z5jh+(0bn8#m24=^%dCaT%e)q4X5TRcERmrhU0V%|@BJu(AzwHH@M0(gXIIT!GEcZ7 ztv8~ow@Zvwl}%_G(-(#fg7X+7zK`yl|huLu_o$w@we z2_ykeznCzGRkI%UM&0fw-6q+dZcYNhDQl~}z1SQwi0Y@}ZZ7~2qFZ;cgDaw7MlqWX z&`74wDV(+XtWytkXnpFkbI)44Jn~J1t}v5m<2D@nLeYlycr4R*cP9{F(~$ty-|)%IRTz?qo4&%Y2>=5pI}qWq(a31I_U_W-L9uf zZD<<2=EQ~2zMkz?)QJ2^%2`pSwa~X(!?1wMtYnNo66iM zdW<5yu}*673T4cCz|$DhRdBzcIiLZ`th*Aw(?+5yXcsytYdQJ4$~wIIrE_Ve64cz@ z?lY_v75MG|IU-=J>S7%^HiASZch&3^?O9X;6cAc=f&@xdPdJh^11Uwn-4T*CpbG(8 zMz?Mw@N66=AWhZhVY z78-Q;zJ22cAl22+x)j7B99N1BN%cqE7b%0b2R?tpp-L*rl{~#l-g~$yD&3={d&^SK z-J3(@uyQ*{&M~4S0H|Pm!ha#r9Q8Zf-M+Y0gcd2wkn5=^KJY+j0$EBkz>?K>izf2M zNG`g`VO*OqstkAogHiH;yrq+8mbH>BQ`~@D^v-v#U1Os21Qs#YQmPIGsT`h`@5|)nd~EX$H8f@DM=wGh%;T0LlY)~#X*hn4I@)91xw;d@)9!|G7n{DVPmnr@bX}K+-%(F9_`#1j_2uwj1D|4kxj)-8l_s) zKo0cTuJB*#a=T1bjhi&E(hCUBqnnV>$*if6Z+Z*@ z7rjS{7YAd=6}D`?!i>0%Ws^V_No`m|n~jI-OPiY?w$~O{m!KguN_&GqTWWl(Z9BD* z%@7+>+wMn8>l@1t*4oQ=YlnO~gwb9aT4aeh4>b;wJPYbbB^q^W^G@gjV(*1*0TF2; z30_IwX(TcJ1x{?hN3YN5AB|_9SPY}IHwD3cExq+={Y9YtzS3K@)NI)NG#tG-7b;ieH|Qig)Pe=CeQ3Kj99#A5(RSF@Ee0)gt*4hoFM(*z>DD<$soRMb{Xu32BvJ?(D>)zMSgR`8z2p2lH3)g zS5~^tBRIbl>*D=F?>A~xqQ@bQ71U4D=q$Q=sdwcIkXCSsNW8IxjhoWndiYr%27~#l<`FtiV!qU z?={>9Si)+6JrX`g61|1J%(fm_h{f)o<{hLA+t`L3& zn~ac~)P>PczsQZNoh4hDwuX^T$XsW10J4PKG+~mB&Os0JY3vV&`yg!i%|_<0Pao5g z)_8ib`ved4BDF*}kM|B=N>9Af{O)(kU7ZV>!^53&`{$Vyx~T&4+#Ly%c;SWS*1wFo zv7cuz*pY=v0G>%|N@|Z518mD>y&z;G2|8r#Z+|40=EyUK(=DQWq;bg&a8Pt_ToYr$ z9PT2?Cy5#maV0b}&9Mnqi)R2vorp+32iqzx#`&B-gd25Nr6#WIk6diXdeoax5CI%N zpA#IL;KSo5S0spBL{@5<5=*LSxFV$rD|Whikv+J1q(nhwCikLA=yUFN5}LTj9-i*aYbUT`JAIqw#V_;g8g!~sLbP1Yc>(jxiQi6tCpu9GsT^}AO64O8=fa@EZZ-(n#O}{t_JL)h$7WoE#laus@=6le}^_afg4jqdlq8ny=`o2R8_Bp6FBt z!<)ua0fpRruzEkpK(S@%x5iJq2NTsjQ~YBs1pJ<%y-r!&E=nDkducn?Xi`~*ghoSV zi-&J+mJ$4ni7QIBFr4x%JtzcpuFjfcjueb%=>hbrI=n39tT3<#zah?{I8P5{bzVRa zf5KU2G5+ZU7qmDXm8F>RfP9vZB7VZXgZ=r0kX~>q-4pq*vRq2#rL%DkswRv-S>V|H ztjOy!C2?+d<%fnOk@>2s%d9#F zbOmur$zTPVC)y6TOt&a7EhR27Uh zGd=lYsBPHps>UXZJ}aAI4|OU!xIHZ%Gb7YXS0IBoQ+Jm+^=L;sjV;f-@uKq7^5t2V zOnSIr%S1C(nw*$qq~LrTa>15mIWO4q7mh8H)U;p;`^B^6nIO0@hzk2`ymWr{)1Be* zI~j$%;AgVb`kz;84?Q0GnT zju$KnCvVnueCaHz>>Y@ksaLFWosTZp>Rjj2+MxCKd#|T+$@!MTPhlodoUe-ul}otX zh067XQ@Nsp^M&Fi()Fwy6ntcFC)Z8Q^en??UPN!Z}LvX;R4r@Pa+*364~~hKHZyuGhUB%j^6cU0gUyUN}k` za=t>l;8Q#Vd_k*VV;+tm2$DP5#tSFBf?7cGK)kWUA3I%r{qTZ5{AxFphm{u$Y{u6H zUr7B*9@XX??1F(^FtE4+@i)EXQ;XZho3t2lB|AHLs z&#)_q=dqJK#l2uqWukncVR1z+7*v86>5Jzt*rVwS&x^Rv@>^pjCVAl;sEhT|JufUw zP^v{;u&9Wluf22Nxo-R}uBf=PjW4+41*7E7qIf7x{ldIL6K_H&Q>}f(^LQb{pc)uQ zo#UDMVdNwazL}CyAlm*Xy~A_$Q4M;s)tLW&8aOVJrqXYXQ=Y}m1j7Z3l@)#Y{`VdY zFhPzB78|kmwP&&CbBVd&vE14(I*)z9&{+%%`fMhu{HpyxW(MTKOi8r&PI#ohjZ3*9ItWM4&fiO;P0y+r*jWr<@0$)3d2NCV_%WEAGfz;YUVj&Hu#=?jG7F0?%_?`1aQFRTf48d%%Pfp_0xha|-XF?EGcN6eoSSJxj_B(pvzd`vyA9@poD zP|@&8aVJ4o$5ZT~rjTN0O$01Q=vn3vLGFY8aEJ)={oWHzKq!&GOBtt7u@a)bf*{E4 zjN~&mUZa9vqXUM7=8@d8ET4*3zOdsY0X?&aSdL~S$Qq6ax(Ahypk0@+^m00xVPtZM zgejl@?Z5fnr8oHV+2_rleMK^&xbOD(^Pl{^KY!zml|NYd>;Km0KfBCaaqXjF`-y-5 zXyuRb{Wpn#{b2{^vJGmA%v9FwPged8iz^v?toTn?{tU%mW`2}U;Fs6lIq-)6aOJ;7 z$=BI1lzPN_Yy97={3BHPm40WipEUgMR{j~jzQu+tnE)>w*8gMW|KVsz9=<*7jCPYo z|KI9cmr(RIh0}`rofG5|(ZN=KWXxL{CrP)JKb^8!P=$OpGX3jdc&t8cuS6;3dQ6~6iA>P;4YCA5^J;#T_YH&^en^sCi`V^-t6 zH&_34Y0oLd?C)0kH{M+R4_W$a@cS4YwI#ER75)7;S3mwGLghS4vYJ@o&M&Qg%EB*u zA#;ma*=N7B`agaNWxrL&;jGU8{H4|Z8+9hc`C8cj!JBWqQH$A9P#RXgmEn|+U!Srm z+DkweK_~e(Wv8X=E9E8BA^0`)6cJAf>kgk3)ML98m5+~n{4z(0m?z(+9Z+qMpEUWF z99Q{!$_`0cMs2i5A6^fSe9Q4hK2=DVHV%X&u5|^arDpkvls@Xw;K#|&zIJ#bd4pP= z!yfX>3M2UZ=<}cbPWpYX-x)t?hm^#hH~(nkSKoN!3UVjiK}K5SIDULoH1Et6@7%og zeI!KME#B`SLj|aK>oO}z0u7{TLty>`vVGurUzC9 z3E_x*{|2}$QeXA|`@J260o;Kn7P#BE zIOLb{V}P~IZrJ)BA=oeoihImf*RuQgXPWlA3WMD7S}#3 zK3H5|UtHV#@CTBV7WBR7K1Bj&_S8E-zyZt>tI7-r%qffxR+rZAypI-(?=Ih8-u#eq z%f02zwWW=X;@*SxVzGF*xW2i3=h6Me_2S{9^@k5OmRbc;j*6s=_NS~Z^O+nl!zQu| zc6$A>&iO-Z=lJn(0#W!e6C8t&cOmobmNFer?-zr1`a>{x$>b(+8x45?*zz6)fa}N} z(=Gns@zK#C5~v;@AGh`glh$ywe*=5ZeIMWWA)#T;nR`Uu;@$qFdpLslY{^D3{M8$dTE*tD*d1P$bvOn> zBgJc{xJtO&?B%NF9kZbV$QZ+Oz%W@2aJw@)X%)+w0c(7jFj|JP6ar3a7XTnrmQQEY z-Dl3MQS0*Mdw{q540+&?w^jskNvV@kil;Y;hC^hOeX8lVsx@wf8n;w-B~3*4K2D@F z&8Nr!i1fs5EFhkgEHrL_NZojP)AMtlx8W@&gbNEdUf62f2sCXB%o!gwG%?vJ9p9>h z2puC|o{%}q6QoPV97$Z|r#HFff?!6%KDMcRtcl1 z4~HN}3lcA(c-re8xA!K49sB#*HJf!ZD=1`a>v_4#lZ?t2ZAhSRXHPDJE{E%S1nGJa zp}BmyywTbAPT$mPly2G66R@ZKaWbtkq;-p5Zmooa3oP#~Au&#nXNQ<*i+mR1EXWma z3Pr#VAd9Vi>u`A3Y(&ff^C-@!L~ceEyUFjhgaRsq`t#!imsvX#|cRLgmOrV2(ZXa^*W&8^g zX@4=N4&s))k;m@by^cdu}O zJSsgv0W+0I^3Vbg4!!X3c-MbbBW?I=vTbd&cRXmezkQ5{eBX1uc)0v<$s18AzpV9b z0lYG98FoVolW|rh)waEQovEkV2-;K+*@?Z8{@JE12LnpKTWvu2z!?t?y-Cd4jEuY+ zZDgZf-(0#Yzu#M4Ti$q|f0Xh*BOR!B0|V~PkxxD)hs>2tb({a@U@*g}kDgqBWU9f= zsM{er+Fp+)gSLIj`$96|$q{r-uNZ9kyq4%-y`hNOcHmM1seW5RroFoK*=-|3GmO30 z3tEKqcgQAee-eszyZ!Ew*R%|$kGnfh+S1>cHf<9ha7OO1gt{MjAY?D-#8mvK$I0yl zPLzUSNvv`8A-Rsl$X&fix|3cZg+!?$c+}q|Nzq~-7brUdNuu3#pFvs{1=p^S2v7u* zh6~ZNKhXT+(i7wk3+24GSZlXUF_pv!!3H7-*BWzk#kYzd3kWWog?~#Kbf@+NguB6>q!;St z%rze78eoe;Hl%TC$$mxB8w0MU{{>X)A9ju&H`&WvB4!dUP(@3VF3ZKe$rlU>(;;d~ z(`-_byH|3cYnd(j2P0&`F77QZ-(R{*9OOdV)lPO# zP7lhSV4j%7nG7DlDVVDDj)*OszN41liS8`-1B>7b8j>XIf`(-&rMYJ*kV9u*&Ty|o z|9AkF;^;ADMfEt_<)E)6$mp1tF}CXSG)37m!=`!A6HY_5Q7n03s-gP&qqVi=wfEdM zhCC!Yk8!~R!&tSh9Y(J!cA@M9`eBmAk|9!@J$v(PZi4c0>q) z7u*xb9Ke_f7^?3Ol{#3?sFQUEr+@$NWJ(JNQB-(|h^noq_UcEFdo8l&P4Qt6m|K9(jImH!|)G zRuzgV)nU$7sTguh2O=X(w<1G6FN?mT7b+uV=z`Sd@&Qn87mr|QES5pEY5pG`Q!oeZ zj%Qk#y;Oy%C~b~O+%DdON%8RP_EI;rSF6SNwuF9`E}eb%d)s8LIBQ&fh(=An*dGCD zkfKM5je3Su^wX+`3fABVt2w1-6j>!({x$$Wqp_ z(m~kjyF+LUlvebM_P^<<1_5u3i!Nw8SX1#A>2)Cv6EYKCTZP<;bONMccp@#6b%BwA zSqsRKMd3T=IT`dYCEShBcZgm*>c!;aoH&C+ABX+U4yr)9Y~7F(pz@{kE2FbNT#;3W zE}HsTL|=4)3$f8j@$H*n#o#BqxCntu7gPcKH(bR?x4!PYl7t1CSA=r{w#y@a9Y-;V zpkY=H9OV;Po{kFvqJDARy_M=3;i9iHd0eQly2%hboq@2w4psoJB)B%Xjmy5}O^6KF z3*%eYadqb!nsN{A0+I+<2f7j5UUY>79|837V`zn#crsUjKA_a)_l+V1QcQ$jnv->v zazq}>W}K`5nTaAu7d;YygO*Il=?PDQ>|}e43!&x&XE9+hsI|d+A_6Y8U=j!K2BL1C z@FNJ(0hLa5_|XrYdC+7mz1C%1LZa znS}G|?o#UKg}6L+XTV8aDIWHyO=4l_DL9s!aCL{{%j^ zFo8h8ico4_YtRXmX2RdAyC*l4#??SK`$$kPbO=6piE|yBa`9VIq51n!p6d2fpDorK zk9M#WK@TUH)CuN2wUeXKNj`h_jLlK!!6pE`&Vk}&Sl)fM z(>**YaP2)B4M)}XbYI}nI-rmx2?d{aNGrJLT<|sy?oPMgoD(v--G$z}1NFPR8+M1I z@TV%=@~igm_BP6*Y8>c@Ha|S%jlS)IMVZJL#hb?GS_d(P90tWlNyY%j(_fD;ki)zFn1j!F=;+MwT&CVEh(1Y&WxOltS zXV)YwbC8MNZkm=ihefK6AUc+;1$V$!rHV2HUJH2%<11k6Q|;A=Sko#%^Vj7r?TUTH z`Zk-K)^!S}bg7~J6o{>cRBSD!w(Z^krY{s=uQS{rZ1$tQScAhMWYIGlq$9GS{e5OT z1MWK8;CHQ`uY}E>WOeH-yhA4vMF#7_i6H9)HRcf2>j%JiQt8Or@^H{8cNEX zB5u8H!5Fj{7qXFSX_DNO8C6!z1V@(kB5JW}I3h6l0_F3#X95cxgy3|}3B4^QOck(b zT?B^uw4xp5jQ-CtW0yoSdy21l$$Z?DrGv5A8dUNCT8fGUW_R%32(xUO_j!&og97;J6-WL(qZF&IRSI04wVei!{05eBIqQ1 zT6dbjHaK2wKDhg!m@m|%NC`x`D2ysn+=rODw7&jeeg6J~_k6~w+Wxh5Vu z5v%T(bVsxDZ0v*8wJJyg1@!lgkJ<>;^4N*5*2W-x8KssG}`DVunKv; zYJmZj2E+NMJ?KtwjqMgqT?HuFut~7H$B1^r<3blHtcPlabFCs!lX0SU?{p^c-j$AF zgOcVw$a+u}AQqX1s_G?K3aw&$xM9Nu7py71mavr^_4YbD@U0BGFJGfTa-G1Dibe$S zkELj96=c9ftp=`-Z$$Z)P0&4bKv=~fc|PtPdP^~|gXC~@Ix;KH@h{MJ>2|pN6Id~# zE-D}4pdmM7wnk6JaGGNfmo9{NsetzcKweQ87Gl+D-2qvkgTGTE%wS=WUMvu9MWKCcia@&!w1B2k65`O)Mh;> z-ibUF8Xv;aLrz3Qfaz{>0BZv9oQ`2UR(y2^3skQ&@3+d@qx2@`S13J@nPD&CF@RM| z?AhkW4D(dz$<|%s_9$*kAG|{~L_<#<_#dRFOk2aTylY1ae%Z-QF@}s!?3|X-Vpj-C z%8&z2DC{qnZ_A>>>$^NGrXyguEc1oVYZ_m`vpl{Bb4Ta_uHryadIJ#iK3v&B$@DU7 zJUoCQ0_!@WVkk2!fiW1i*|zZ!U5wPk)%gAR|S4iL!b)N+Xk8Ec5|Ua5=S z;X!AIuefB4x*AShG~yCrwQK7LDb$%~C(=Qss564sbLWTxQ+Mz=Lcr1K~p(F2h1(}F1=sjJ%aCz*sbO8?Lsu1C}oc`)Q@2K@T_4! zHJf2oYNlc0;rqj5o)AYIMUBn~=Cko1mZrNJs>G|c8%oWxCApvT%oipJ1KT1s<#r?u6es~rZ#w5 zoW}aNGcpIuVEHTDLNu1meyEE#*uEYjWM4`}v7n_3u&g$6k z8*2|X7JszVUS50nXtTYt0kt*z4xxM_eS0fJ6+YFxcXSr=5SDfd2A$&0;@X|1`^s@J zMD0o|-{nHVX4KvJ0CWy7eB`14L{V6~x{9H{jpg??m)2Khb7(|T)0jSqYok8T@^7X=Bq+gUq3< zDr7)K$EhfZLkuX*D2$rSUHQ&Kh?iVEoFhnhvhs$UGDlY8PrVIRO6qK#GM)&93qYA8 zWvKy(5>J%@>^~~JMhUU1zocE?%3#E_lfs4KR<&`R;KS9XJA^80V0!ZOELneoR<$Qw#wB8roXze33H!-19~w=0w&^e8hyYk>X{pkPO{af4DA{mo<@kKlLMRdt+*<3 zY^v3!!icyFbq{b0MG{dZ%eR8_*piQckMz!8<#?1#s=Mi92o8?x5n zu~^tcWqGR%DhH=m*4`iCDqCvf-?`TQD6gGR$7L1eXvL7bP2lZgz{GuZc!7Fvk8i6* z3jo47f-VJd{h|kKibw)%!~V-< zljEJ6WlWux?d@ z9~|Yf4&4y11dQ=ytS|3Srw>1`qq*W687HaZAa^1fn3!$)jun9OlDw^ z+ZD_atg?!%j;Q*wwPG5B;&<3vxMj2|qOCoIEjrtLnakY}KytK&)H2PZqrjo~=>)>n zuFOIQk+n_ye(#tI%pKAEwe%NYAk!fM;%&SZ?lV{iuF7{Fb7j)!h+G6w_Jz%f+}AWc zvbbfZMUIp71a7Dk3g)*(X^pc_ zADOw9k~J(H2ZzaRyVoSqbF{^ib8Hy{31EA{0*gn3-m~J-=AHN=0`K05XUj02z@|8a zAMiF@ZYc1e6SPc*!WkgaS==MhdocHbotz!MlRz8dIY!!6I!zUwbsnA^J%;tNiGBwY z6ywuh-FUDD!>%AzM95@3y$4jB40!mH;kJsk*l}F-@G&uGD?$kv{y`5H=b4Ss_K@ww z(l71YCQYoQ7mVNJB$Zw8z$kwe?{r|mf{eHue3&Ax3TEqU-MdHVW*g_E#;oN8y|X>0 zN|y-|inD;J)@wMS{NP=FmFsp!_ya}f;fVAL5SRGqCcd&s+U5rm(WUexRu@o9@=Fz&Cx)uxmLrXoxc5%VlbI>^c#(^`o3mS#WmNOls0q zilwr1Lh3};58#$(5?F z(dYE|uy;j8uc#*6Frt8NQleH=Inf;Wgxo0DSd}vcL%C$Y!T?TEUg>0J8Bsu)NgNc3 z>eb3-^m}wxo_N$i6_Hy%jZI>#9_Ezvs$VZNTvHNpO{OLnrzZZvrYN$b$bIifZ{t?c zz(@@;TP~hMpvWXDI=S9)2O&6oE={DVIUSa@U0Kz^|GD8=F`)Iy9$rwFIw zYZM2V8DhxH&ku0|Rs~|Ug?uUt&e;j#-%ckPiL>DJZJCG7QksEW(-JQvR#~O4GCxey zVtK55rEqrP)qe;9Xb(}f9zDWq727mj)${vy+?lGr5+-%*ka3J`2p^ES*mD@E6)Y=1 zCpGl0hPWzg_6nC-dxTWs2*{IS?a z1HqNvpZiVBbZpCD#9Iqq{Oee9DTdwnD71$!h3`Yy|LAF!LTE>p$mPYP+&Lt)I@zzb_qU$zL+C}UO)2^i7 zZ{b!LcPWvVCD#Jt2gTjdNrc7LYgFknx&O%MM_eq-rgRG@4HKmrzeW$9OtWS${0SRE z{+q36gj;L!p^w~bIfu-#IMElBe9b0293o9_y6{73YySL)A?0;ID30Pnv)&gbBP8dc=00KXYU5J^ z``?0&~ECW`pUC_sEe07&$S@CE;vU4(B-+`$!gdB^b-o-TTm z2YX<+wiX90aSe?)w_*M8p4HS{%4iU~+3YnzHxK;oZ9GW66VY{z6mP};mbM5Otev?dE^jo1Zo@SwSdC^`hd?JLYJ;A<#5I|c8xI~={X#IqAB6eofcRDMEX zM>F}J9Kw=S$cTr|8zgBxUOu~|qy4Bc3vVRFE0lZrnjEx1*EdOOWi3QW%V@V)Pl!MY zK9ws)TSGnwhMzEKu3o)4Y0fymbRiu7G{%TH$YXYRu>soH&9g3KXLSJ$6u4pRwAXl zEZ|p_Wi8a*6>68&4&*MNP4NG8o*q6p8h}b9efWJnk3jihRd$-V-?JeN_+_VY2IffQ zW`EhmvGvv8f>CyaY}hKX^u-PPn<+3JKTJV9G(~Ow&_(>H$^qqv%^FYCsT=Nbs3s zfr~s2$?i8Y0ehB%s4#=HLB31KJt+P9(&F6@9R-z7>IIFPe1tx{Uh;LaNWZYts!PSw zz-{UcRAU0ZP=Nxn+)tY78O{L^ym(%`IrlLN`Nv8qN;UkCO6fVaA z<#%BZWME6UKrx1oSXEvDAHhacQBrmyl})5pRVd*bA|6G)i-16>vxCkRp;se<%Pe^I zgP5OOae2{1PgQUdqN8#Y#Q?)LeEvYg>d=I1@Ajp!OFTMW^$FdqOvCK&Agum!LAnPp zZkaGojAWpM$Iw*Q8|)364ck24Q+E1-B5DD(I8j&;5@z+@#ZpEA$b@2j1to*??Hp!q zYk+|*_#iTw041P^ZFjbD$w|MXIg1&D)t3`3O!=UBDChd>&l-~nC4wTmV3 z@Nx|P1p6uf5HPr!>B^<^Mp-s*Hp1LV+)Ky8yGrKI%DE@LE3<;s^p>*?^?QF}x_T?I zEq@I6Pc?~X%~Uf$|5S;Hz}i8rf?&v5iqpv6;IKW}VHj%U^T7f0XA?ln?JiEQ`1_e& zZmS*k(SfnkEX$(AJE8P`R2J!O3}7XxgrK%kJra*_yln)8bCZy<5PP_@$ty7B&!Xq! ztb%h06;u(?!&b%^Cs&FO;AJ61$QBnp3K_t^dXl+rez;{~1_IE8?h`Hk$D(!C1=_N1 z&)hR0l2x5;zZAIAc5Q>iJ_)OzhT=r0#8W{85*r<>78883rM~st>6W;d0Dq>484Pn~ zn+HsmZ6=+?@(zZ_0VtwGmALaOh$XL?0V!e*2!$RF5kX?G|A%;lgkJEj=NPA5NF^Mp zu|f96NVl9_U=fo&DSpUl%JKhJ(Y$rDxK@1kX6Z1e{6Q5Td3S zwGzbFl}ao)Sr?+WT0|dN#{6ws1dY36M_Jy?$D1M%{vdR?C8^$Vg0&dD2QMQMrxd*y z)z<_v{4d-;N9Tx;DZCW1XB;?gXM#`85sZ;8=_eN}7Ko+Bf+XI55SfMV^%2`#79u$S zYUNK|3rSs~1N~mF+edsyWdE7)wbX9#oQIM-(+dvRaS)ROb!pH^o}uY?i`Bu95^}f4 z3#RZA*xl*{=4;W{*9PA09*&27Mk5VQ!J)ao;}E7E;)z&CKn(aVS}zD62PJ6^p^zoR zE(;(hJPx;9dEeFphqm@>OFvp)B+*Q0CyL>1hj1$N&y^XOM3$l?k^ZGTNm0qtc>W8% zk$Gi=u1>Cni&a8Pi~tCp%Q8QIfETAM5Y`mUeooO{IIe1*AX&J_KX+IcHD^}U?PNk) z5yS2zJ-ae(3`FN-Jx-ZcG9H#ay1T$OLrmw1IdxvFaQ3W1H#5#D z^jbS3>21n1lVX`R0UKm>vN%%x%T;4Aac<`aGi4=+u2IE3PCt|<2Y!b{GS%{a9 zeEZaCl4Zdgs@i~YFLcuGR4BRAF#BCTjR&neknV}i*l}9O^2;G-C^*9BFvXstcFrJ; z)d&i2;}$`!KYslvTMg#X2!ev_&_7?28*x&pxOntQKr&%*d8j#;gQ)MxD`fEsYVIYB z987<&1eTkQ^AkhKI5=S#ty@sxK6B3=l{Kf5AA?n7?Bt61u?h@14DQ#4!7o zI1dXvZ~~Pxv%su_eqAVW6wn1E6rQJq&&W(8r?KUT3`A62o2!@uX_!{`WwU|_f`bZ3 zPp_pD^CoCdgibJ!hRrY&BbiD{5dl(fu0VJ}i~QN)?DhkTab#E9BJFv)FDm%d^p(02 zwO+n5X~<8JN9HWvlF?|UTR*Kd7(3UaYolZObL~E-{{lC=e=#-=$JDt+paA~CgAVwy zH@BO5-6d2y-Ku%PWHe%JrhF->iztsxaXqSz$=ETmparA}X+kmI2=}01Id(1@UBO!- z(FDnbZnALe<~!f1(9e%q^l`D$dp8O(jO1s;^MJvZoe92 zYm-sz=n-;WB8@vVS!nRLqVp72Qt)cX#NItifvgc$3}?s^Z40{)LNIZD@p!T9Q6p;| zc6Oe0BnL7ny?lm|nsu?0l5xYg6c-ziRgh9bjG~l)E$%c#-F=GMhAuK~Ljw`9H3O0? zxUhJ{YY!?ygpxzb@G#uUoep!I92~0uHX6&t9f$1TSr0C+5g!M+oJS{k9R*B9BVPR5 zif;)B(hG&bSbf< zNLM6UK)AWZ2819z?0_3$st4{lG>MwVX*3h{sW;f*9aar+(iVI=x7g6&HmK`5p1A?# z3JGsODHdQlVuDKpu;MyeFM*R2Ae1YkSB!Fiv|viCcsX0_PAEcgx`Mep23H*Cfxl^B zDlDw(O}6li38+%5o)?;+MO+ca4oROVh);)nj{CGrO}hvrd3GhHFcnVW~$f z-X)UL>{+!$skss*g`%dX%~8lAS(Iu-vgj&OYE7qsAb_#?F~5Q~lGqMn!-)R{MquPu zuGrYQ1HmE=3?m4P59L4f3W-pjds-&e(=D0TPjHZjv8zjJ%fIq!Mz=RLjy z_8_<>w)KzlW=t409L20|_?lPt(`j|1IvKfwzKaC@<8`G6WkH-}*rJltpFx8b$yBG$ zDh+6{Y?D3(j$f^w_^7NA=2#FZtg|r3!M&y9h2BabM4^^EfuF=c_^t&urC`nq8~fMnuk)IH{u|?Bm3|}KoCzTTk*&GkFC?K zOe%!V((>UUTWi_DQAWcB1F>#J+5JkfJ`5V3=)5z>JWVa4y3T+WLVL>$uXD{=8{`0^7_uqQ! z&JXXb{r=~_{2mat_|&UaSijRoh2ORZJe!PZ^7qWF#=mmsUqg*QWi{;MlRN(&K7K2G zp~*`AgVjI(Hi~|W3xTx@CUh-c{lVL-vn>BjFH>u`m0o>&wa?OTrS@_wJ9&HcUuW4j zg&Zj-u%f^E_UgYa&D7|WmHq9vSN|K9eW!FI%NqaT+pGVG6@FX$&F`ODo&WLe)&Gli zeoN|bYHDupTlxR<_Uf-)K>4?&Jl?0W;)@qn{|t-2E5+H}7OU}RFRae6#&@g+-cqt5 ztis%d)el)gXRpCSR`h!pR{v5g(zpvN`uz*5e}zTAF5S}9ZUuks!s*c?aJwY6IStwUR&a&gyqq@|&D}R5z^jd+)4{u~hp5+S>Qa@2qa(`-$LZzB_;G z!dq_@aaO*SP(!{}Ae7cF!lV7>m?_^P3Tu@d$K+e}L6M^J*2?F6Kax+r5Avx3Z{&Nn z%^HEvw4O;1i;8^?bZYBi+AuYK4;YX6nPo#sVW z6-&E_{4n@~h3)m)Fq(Jwj$a@})sJc~yC)J7jiiXkGSKU6pGaIjIp73nITE>d_FkeJ z2<(vGO)Wt}l>=8FYPat_LdrF~kb|hW2PfP6NYQh*v%|ZbB*RDi!dGo!j7K-*iMI&B zLxTXhG^rObD(6Qv(|kOY=d>%d)*lm|ppOQ)Fu;atc*JJ7Hv|EZK{7qh`C2{mIKhw` z^(ja)U_ytk#XuNG;0UaES1=M5qxR9t`iJ))t=F#K`xrs{Yirle@yOpYi0f3^23L+U zZGGj&qr2DFY7ZW*JwUuPQfWTK`cS+@D!ajJOL_Z%!MoMLA~Fg(BolZ!hLN&7he zjHFtJI`os)zT8G`Ec-isCf!S9yj5S5+@ZH%kr=h^uzFdic=>DRI2x#~g90&6DG^QO zK+3?oq$9{XktXz^G>z!vZJiLROFW3Cw+Acj!5b&23b7h=>0}2e!FOf!Q6&++*)OC4 z_R|dZWb6`N9mDyH_6yP+C82OActwp8kS=Nx{=%d^ZkVZROWbJTZNk;NP?V{G=GF;n zx|^HG_I|v%*?>|mC z6Z@993TL3##>tRB6aCGf6q9vxx{0NwB?hM*7X}2KML$M|utWvD1(Lfp$Q21~(fkRX zJOj)Pt7Cp!%J1nVh>Ce|O?57kub4>;g!*$g5y8s@!{d0#0)zq~qR-p1Oqol~`gGkr zH%1TuuMi%;4p8tt>;2Zj_HL_ouvk0rm%RLdO=s8)gfjz_CRFoJP}dt@E^1{NkO5*jj$%`EOPnp(Qy- zVXCZJ{7KH(Qu2Eq2~=!kh`nV04zFw&w&a*L6dcErCI4l3-@4sPw(CQCF3^Vj&*7uU znlH(Jv$OmWB#18WroEtxAn#GA4JoPJTXQp`QbAhe<)%&YXghE#?}8XsKEaURL7DdV z5b%{zJ3O)*=6|VnQ{eJ|9VKasIv{NF3o$%2z}Q-9Lz4XQV9Uo1!Q;pI0gqrv9UuL7 zory@-r0lkl;`Zzdc~59??$;)^2HDsVz&*0WK{G9E1ezf}8Of%qOA;DA<_tC-+nNl4 z3Mf1ZP^8R;?GivR5}1tuCz#bn-P+e5YcRsAfURff%xh^!uWBg+p_iqEnuA${;q#1ihtkzhi_1Ni*0Rpthn7v=7$vZJuD|DI@)l?$vD^NYnJRrD=NH`Tx zuhb@+lg%me8Ktaky@p1x&qE2^+bWe%8h2t5NJ6F{cxwQl(5;BIiKl9qtZ-X3Oq2=kBL zLXR_%?vgPA7%6h1+!2i;FAlaI1Y2o~kmtgJ)snNO4P+9$NFA{?XSPZxyf1nCRCcZ& zH(Bnxp0QJE>p@vb+D5+_0WJ@oR4oEfm>I>0bY&2jGiZ)kJ?e=#!Wn=`%gfEf_9v3p zbLVNQnw$yTe&XiPhS_ilJg>AKy!sj(rs&KMT|gfbW-4Y{Sn-sO(ggVnrL+>B(9eY_ zAG0NgLYaXQcL}aj9xJERB&C|%1&h0AbdFaM7{%;q^fV9xx5Hj)0}8gxtB8NVm%{CR zqFp4Ee#0NS%uH(DRfx`XPScIQp^@pbRq64i9x@(JKvb{t z@#Rd3BIaKMwD2(jqD22oN zE}N1K|4xN+RNw#$=XtOFLWjSN^qZ8CC7ja>8rZ#?anli z-3+x{5G8KL5_(4mliDL_3EQ+wi~bJRRqD$uYxb zA$Ahn2uF@~aKCAujfw6HLxLLMX1o~TW5#lOfmz_62s0J9j*zL9&rdR54;~9#FS97M z!UAUfhB1{oiMSH3{Fks?A-06M;Rq;#uVbgwET?a??svP-Ao<|Mbo%fXEqwq-8<)gmmo_xaLP4x=c(TMShbKqkc7gK+yP*A({qJ{Q z9za=%ZMgMI^#|A2KdjxqRlB{iURzs!a39mE-MD-I-f~)TZ>j#Aj>7;(vaCz>38=Ia zI?#lv7x%g#9O5MroW@90r=G$CbwqC-bgo0ZZKzv@eI%}Uk*1M^tMf{YKF@ym4ZrB( z-v}=>q4S__T6>vw>jWiqH3~ur)GqU7j0rd%37=|Twlnq8`)%A7`~*4~s@q1Lp@r?> zs4Z-B>AfAb3HNsNx_hHmO}1T3H7PIUT9N}8|EOT3wzLQfJ)+t~f0z7j%K;fcNh0G$ zkMJNVs1Ie!Kp0M8Z+@mKhFPi}k)M6=fZDpv{$D>>8E9hH7x?g74kH~RPRNYS_Jn&T zPf6Mb9*D?n*HrUsVbE=vFcxrKDA2j1E4|936G|P-T3fC*#BmcomGBH}oG6lE`a0VZ+qXUk_}@Wepu zCfsl|ws!k?(}jD7*DiZ%L#S9hHu8FM}SCbRwbTYqW+@EYFQ*@3i3bZqj>4qOHlJ=?IRBF^f#%~ec@&%q{IC2e?6w4WwS zOt@Ck(4F9zn{>c8bPnjY2`6*EahVSxP|97Ze;-d1B8b1y`QcQmITH-Id1|wl8FL)| zK+{u$AYeSml}r{Zc&@?L$G+bm;}Cn%B!v#NQr_6+V2|h#G?;1q!hvSgAe>-B_+OJ@ zG!5;>AvaXjeo~x_E7AT056dA!VUr6%5-P~9fB2gCU0|vpn%)!Amb{c~@l@KX##R}I zW}T-9<^^n$qlciF7Yk5};aE7XzQW140l5`#Q2Y|M>ih5?shEs#Kf|ME z2x;(c&6+Y0du%Qxs;8p|EV1lfmSpp!Pw5hJWzaRDrov!gVt$4<$pGA0_`I-!9L{wP zt)OHlBS;rHF-AS{!9DQFT%Ds+T_P|^=(!cbs{ zNf3Gqlv+FzSaJmVSn?N4?EeM?q=*sokk+Cc9UW6zS7y}0NOtI~8Rcu_ zpu6I_m%cP^PuVKa-F?281F&J`wZ@9lGNP>!CdD0skh2!2E_P=f*p8_x5zHbC+_Cw= zX@sSKExA`nAYr43VN`nYcrB9C7d^&V1~Sq;QV)?*5u*Na_ecl;4XYaa12PA3&g02Q z^<37+uV$j;S2xx2ceOzAHwv+R{*v465ca^)6xKluBf-ePG8{g)?bF~#wYx6Pp?Ky6 zDP@dg94G3l9XwW#br@sIv6zJ^o9HWbn5;KNClBK70P2}&ep zEqXDB5vBTy-RU1QxW>Sg5fdYxiH8=S>Q*DH6Bfu2Y59}Z0WVgDL^c*;Nr(of-`ikm3=$IDuiA}Scbg!;p^c24q1r2J70;asoJqmc3Z!k zVV>4SoMpblS%1T4rd5Z`E9-06w3LQ1=ATY_k=1y5&GsP#?y~*?6HdC#(s1O-59)7_ z7l4R_BVn4p5ZhoW?;Sw6}hkKO_ zo$fQ26EamXS*aM*AlJU=_I4q$v-_WuV$$TvVwmq_`z`}SzAd4F+5n{ftlc|o@8fMn z&oa3GHln7mouIbR9wauF(p`De;FxT4QHmJBnBa2&m}e0wY6bB&9D3zT%No#!OMc8j0J~_dCP!Z2@%C@_$-ma~I^;lj3 zEf_L?Yk4*jqm7ce2iQ1yhplSrd&oNR0^;adF+dzJHrdcedAeRSWWrwMj2rIFl1Zym zNEA;_n^=j=2k)_>BXl zN+R|^YOp_Ddq>tt8l}X~kc^b*{4wUQ9CnqA8LL&n?8{I*NdBF+E`|Dm1@;}~VB4Ps zuqDng1KT^SkyqAza9p_}cM#(F&vmP+mU#^@W1du_5FGSUZ6mMpSY8Xn zl{GbK@hA=)djyUlo-m`n(m(t&Li!AN*UtC9C|MVv|n$uO^i1<5~bOxjg6%eHf;{c>6S zn}9NjLobun`nrV0@FB(UA_@p10xoO5Dd40zsjBJ zEc%k%^$BAe8hQA`jqV}v2AK!k?l0j&*sa^Q7zjaH3AIk+(r@D!*p)8>_jac%chWZ* z5sJE+{Y*wsH>BY{2j-k)VzwLTYAr_HO8|jalVLp~Lv{VN!i^~Le;02-jmZ`FF+nVc z^iu7oKmBQKjVxH`hHyv9vciSHh{OQ%V`*cvBBY3rkSkb?x_Dj3L3Q9!(-$OkYEPN3 zNdxV`rWrS*A$f6nx0UzVcX%m3#LKsq)Sz}>Wd<2HNGJ?0ypQxrKnKqcp%u*e#d7RI z6RTnABhvOd{$lL|2@Mp#e$v`Y-IW<5`L#aaI3!Zw8X9ChJ<>^?g=+SG!E{&PiUrm(CdGkf#y{TtWsDjCyd)@LMQ zZzOxjnAO8S_OP98AXm@E@CPUOj(MC0Xd4d%j9NIJ?W$emeWVU^TEy*qptTJ-6(mK@ zFK7Ss1potc5!_2DAYFg!xO(z|!k=P*enB8ku~^p)?)3(XuGAiO5KFq&w$KHaX(he$ zD`5aQZ`*cHVXzktb$3~sV@AUo=$;WKt=UHc=q1@lK!~VSIAn3X=*1=swvGDs?oNLk z>4nCrj;JAz7O8P~mpc3AaYOV6I)ICCuRlR-?@y=?Mv+S9W;i4ufQ4}-P~9*_a+`t9 zX@DUDj z-?kS*MI|f$|1)WZHF9X8RdFy8z)5qMmY!=0-Vfn4eO*rrXd{t2(>$* z`v^Vhz{Y^rZxJ!4jC%zM^<-(_*kk6qm!6Xl9eCedY|0bKMMc4KQYqveBHNVVxyoTx z^L!oE(PElTk*w4^(Pp0;u4+v%*4Y>poHjl zkR$7p#$`Rlo2+09%wI=4%F>q|BZao1D{5y>4qpAy`mOPKT8CC_dMY3#{L%Oo>Tql^ zK?!CgtU!tV3qHhJP3m3lfVPMfy|7QhD2sR;NSTrPi=M1lrr-u6vrDa}KzLTg(@ZS4=2 z$UY>EL#5C-aHIPxA=x)+W`fktl6cloOS>C^mhnKiSdtkYFkNi7p$9N{pmZlgnPzYs z`L>$3MLCF6;F8N)t!xhbMp6&Q7` zV5EvI(vzeZ7$mBsGh85#D&gp}6}U#PPI$KWyW7g_GsyT=413!ryuS^>OimacB-!ci zwi|ZToitvmJ>s2J9BC79h_uNPVzZDtjp~WW@s7a4EC@gfw-Kdm7AiYN!sVk-T?dgf z!o-%FR;0l53pj=#3xC%&wJKmW5IBwzcB<+Qgh*Wrm1Az<^D5@r{NV2W542%X$^hn# zB$UeZ5)$VC8zqInQb|Swc_ZkcmD!TOM<`OUB%;-hHp#k8yWy{q9Ii#xt=Hnwl+AQ1 z!)YUTg|mG+wV}WBLnic`mpHORzcBS2a{D4XI%&NK0&Vy0#d~~N>S+v1!6;ul&5K%B@A)`=vMs<%sD_liwobCaS&9Dw z$IKY7thm)v?W(Bxe1JVsq%*u>6FCOhKoCCJK=f9`flRs8OG0X%Q25eZ9e_N+3+qzW zxTVV=dGZN8#K9e7m$VvdS4DgMm&-Zr43qBgM93B^Qu*;tE-3){katw4L3Ynz4hUoV zL7qoU+IzK#VJ^YLfaGncuu}5n!AVzA|K{~R?a@?p(ajp@5$E1-Foc^BrwR8E#_^nk z0Sm0;O;|7|4y8D|=u;-nD*ChmUl%ocFKAhbQoBH9GxS#S&CwdB7xBl*6~&Zo-hx!A zWAb4SXg;9v4ipK!_eQ2k&~S4Z+7aMPlsBGy9h~t`lWIqq zifFJorKA~=-ixZohMGPmuL#5wjYZ`h7agInB33r^Y(w#Kvs~C2QZ^_yiJFEwx=z)1 zr@n+^oy?6_iMa@R?WKIUv#Q~QzNYhiR*&IV@!;|tNgk<9Q;ze4W$Wko2P6}eBU)v; zvKVA_D{g_*+L3y6_zboj1f3%_(h*D?RLSKeG&aMf6`G1K3r`G(p&FGdVW4V9>Y1@Z z2Rhu4vkx*<`TT$`lk-+i{H*7PG@i+mz~)6rz)^awGLjOak&VKN=*gyispnHThsFpQY&bdNI3V6j8#6*?u+!%Z*J4%T%0^L!R@^lKc<15w4Yk z2m3`SGG?B;zzel6aeaK5c&(gNjHCk~=D{uBU8G1gIu;QbUCs%teV{2pO=*ze;a1|k zQ`j+0nm4|m$S>JuI0X~Neo7^kVxnX|e8-qSU1Uoky06KvpnH0h2(xI%#=wT}e-6u70AZ0Tu)QT2JJdxEgT z*U#SGfP~GNol3-%8tR1Lz?F%OZfg2MC?8gxn@c=81LX^Q?V8u1P8>f&gVT|NO-OdW z!l>c1%ITyoWr7s3T9B5$${1n7j##tblw4)#cB*)#&LdjO1+!ed+T4CASw;&amUeQL z2c?}5_h5I==spPPKw)3yrfRpAygns1O@bnOZ2f+5+~tdPT^Tlr8W05G&TdH&N;ni) zlkOKS({6e7v=)9CoD$&u!T!^NiRbn5Et|m*u{z3SMw?UCAj3uPhv7x<2J>3Hc(JqtRZPth%;$wYie$!&VZ$H<`YE+uc6X(SouSMhf5W$*!D4IbjJ&M9!12jz1UaCPR%!HBH_4}Np!f{s$f zh+9}bF_;S|Zg9$uif(8?up|qf!>p)bNWOBv5XF+ZyW(&%o+$zu8dOSmmG}~38VgOr zcf*<^ztz<0G$VKsS<1QH4XyjRzItN(T(;UjfH*0M&w_ z9CAiX_}p~Q_y(S~3>h&6Ydcej+O zJKFQ*a0r3ufHO%6MPF-_;MVw#s!KHR{BIa1+iHxg;R_%?l8OqZ}}^P zUk>tO?UqfO1Rc{%Fe}z66Z7>qidK>-4%Z_360-rQkXpua#eu#Z)VAbm1iw$br!?^W ziT51b_a}PqK?lQayYAupTQZ;fhq(Ml+Lj)5-DV?axaliNOEw~Z|97QYhcH4#Lyx=taeD#=8MEc6l7q3{q2{S{{bHb&0-)_h-iDo_Is#M0S*>q7pIXzg#dh&iJF^I0E{fe< z!(tw{Z|&o7Ht!)*yiw3SV2oiVZo@sv#GN$IEle>I(|~Mfr>6%gCXs~zM@Y=-JTowT zefdn=_x^k~QA{QCLSwfnYctnvLY%`o>0Qfsy&#R!2Nzu)A-S(4{{md@i#Hik8riXz{&Dn?cpHsC9g&VEqymN9jgNAP zig*Yg`!o1H$3`aX`Tbd3*~0aNLtwTa%XcNHQJF);FGXvNED4&GKI6T4y~-+bJ(07& zDG0_pSL{`!`%b@%yUVA{Hi!M7Qx*8%XJfc~_e!c2uSc-F?t~v&=0@??DsX}}yuMkLZ z-OTjsh@&#|NF=V*Zjoiih~Vr5gtWUZxdIn+QVFJFFP=2?awd0cq7Ht7Ujk~W6&_X9 z!J6Lu<&^U9cYHy8yFnT|;ca2<2NjZj@GTF%3G2>)T$gXD}G|iYsp;+XO#9}q!}_$J)^PsJKL%DC%qQ3B6GccEOGBAR7;vvY#y3`q_m$v z#0pJ~aAkXhN+l{4TTrM%Pgn-fnmrs{g@xyPOew*Hljw;aF5Krd1cwITQL4x#isHG= z6k;m`TwKj&uYa_Udz@oEWR9J_yfHpy768|HV;PJTcPTP<} zD+h2;Km0y4iKpLmL<2YV4jsWKCx=XhJrh5Y__I7%F!Baw;eaHuG#SstT|R*j=|>GI zfoRC1K9JrOQQUgH1XcSyV??ZD_p1sZvH*CHOCPMoEOlFjj2dP(CYQj*mDs5P!W!WS z*im%}B);}&Xkvo6RbwojCcJOlNKxGS9>D}bjEuzkInv!d!_L!?v1SzPBYeV>q!8pq z;MA^lX-Ujc`;=Su(rNSPr2mxl-Qb2_&D`b-6jBzwcnTFvE(ot(<|fqV(Lcnsi+5QL^ce z`JgbC45Y35oa$u;6W5Zpq~DUm{4~%m)i81x)$Oe!Co;jeSt4}aend1kOI+!K77kVT z$Zllz2^3sb9u8SvKYuYp7Pyah_x6aX7`m|mkx=W)SJR>#R1K}f^C3GLc6qeJCA0d5 zsm74lwdNRpN;oW!nt=kHj&@>K&;<;|PYh3JPFq0o(Iu?lSyVpRDvCFHNI7W6Y5BqC z;IEfZsxiDb(h_bK4HkHk{@EoESO}QdCMdew7?*4BYe7C&Hpx$;vGyBs;MT!$!Q+Li z=MByFj+f1R7QkibM3S2B7@5kDeGw&+=ZL8yc;v_=!+GJzNNsoj=Kb0@(knl4vqr78 zO%s(~FovB2*+#N9YALtYP@0)0NwZ>z+Cy87jwC_yZs!74JTtN{^h&xk7GNtBCCdSO z;M_PBHF81IcFm@6ii)D6Wcmg4Pi%Bp3CgJgs4^yRK!$Kbwnqzr<+ujv(3LMjdP&li ze_{fgBAYYGEbN0{j@0IM^HImQs#fARc1xH;5tsRi%u&LW+bVcFvom2RC+7CiD5y@J z0sDC^p0H8?iyEf1iJU|I6%sUh6KIhap-pr|XQ(W7_@@n~>8m~>KJQ94HU5`AI@Vzx zVx^9o{%4_=O;)k4SjC|BF`KmcwxAF7yYp8kr>vrJOs^kLn>vMc!Pn87pGTdD;jk9l zes~l-7E6U@0#G3{n=CmR4HkYIMaiOmo=BC@I3kY`T}$7o7lxf_Tr|X;Cr^hnidU5n z$x_n;2h}WbbLZ88u-bh4mV^) zNekWVRZ{xdZW9mVP*URPH}SXLlSKtqjyeOsiC7+WWh>MGdPed5_feC8g#>k%x&g@uH4y5+DW%m1e{xwgxTk zxA~4N4f@GeTBV@$Yf~9w(MCd38QX`HCP^1oxzL3?BPSY~K?iIUqEl=>;JrCrO(4@P z=7E&?Y5TAa3c9UZl{tcIlG`KT5S68{tx8y$gk}152U%3%|1^H~#ri2M+}?)W_*5V7 zS*+DT8kt%MrpR6$e?9?X9M(U(QfoGwmI1P~;o*HEZOa{3rf*P@_Jm1t4h1I?rYgCz zxNx!!JTaiRyTm$0C-voIA7E|LjS5ZJ%yCve+8^pkqTxb77pJQ_5D2Oc>Bvb~WtjuO z{31RW$S?LvVNAXyLaU;VA{uMj6Vrn*RI7}NUG}QdYeO=f_-NQAeo+uNd19l5N2~ba z1ac0bbrA`Yqrear9#4f_7RLn%+mK@8hGUQd$6ZlrPb!*!9J$*pE17;^D$uzpZc#9B!eEt@LkBpCcL*-p~9 zHI9rTXp#QcR>PJ(Ys(?Mp%j>cb{zz?gE%LRNsM%@(3Lc?Z(T)t;ljkZe&e`vybm5K z$ce2%q%YF79q{2BxSZwJNWRu02CxUX-jMkhIXBwJFT|(+LNAs|<{6@Vfw{_1Kt+z| zCI{gm0-yR(Lc?!qh=YtC&s zQxyo5%nYE3NlPxDJ^-!b8FBViJ9F1zz0HEi1yms^W{h=cx%w%z0BZv6@q#Nu|0-@% z$Icv&*@d_a)yv0;$zt_2KJWm79~S$utgU2i4^vm52=4F(VM3;GAxr}ApbAO>p=0|r z{4au`qvUPuUT*RcuWGhmF73Atws(=@ZLxM3-q_SruXp$2sImWa)Ch}9rL@4sRyJ@{3d^Cy!XN_#s`0cbINq(M_*d_}Use){{+nGMC1El&Q#g;+t ziaLO+FMg^Avcyhh>mh-sbmFtmY^MVt*@_JZ<@ABLh)R$?8xAvPRRSe0V}!$d1Ue3x zpx5dva*()i--KceZRoX1hMenPChcbyLB zAmp?uA299av?1jr6vr!(C05W8)A}h*VvW9ApHSLOQPN5jpvX92N5UE;}oE(M~tXhJ>n_T7)+*eh$uP^pBueXrvMWt zND5K*U11Qa62g)6j8@J`A~2+4>B*@}B1=Wt4?wHofWjKLdQ${WIbwu?KbLCy3LoD( z=-0+5xFgJf|A_NK-Y1cF5cK)ptSumpPxYO$K!`ue7l4Bc3zL{=kQ(hO8=$?(p6!Iej(74fT_86?F9bC1C{L?d{dmu$9v|rlSAxK_sJphjqFnX(MKwEiD|`z8xYl)q{M|V}z)^d#q}mh(@p8ge-k{*^9Ck&zDKlY%Xl4k*r4)p`8w%+ot2}0XxvtT49l?o!galk8TNn$&yr|Q`v7qaJTc#`AW(&<}2(Em+T zsVBq&Bp|NghIR7TWj8wj{yC>H0((K={?w{AMXYXIUaaVR1e7gx6L%%R7!cGKO~@~N z?k`#pt|W(GTw;HhoiHn%Zq$)7`D9-#wL-Y^BX2Kq@ma-W?D&GW`J{CXD#(jHzePK6 zMeqJ@R$6wIzWpnDmUYob*Q&)^xm!UdipzH}1X@s`p}gRoa8p&p zvo*;38!BrDIOtMg1{E2uPl`{|2cwS>`>ea#pnYs(Lu&GE=EsS!DDV;)~U(1}ossH}xzx=lHOKzZq(^%o3zw><*ep3t6g0VY|*eb-Ze*W{n z&Mv3#JVfDdYpbRaMv=|>R^!o~pQ6V1iZ#IGtioTo^Ej!X6g}%<^UgLZeAjyL3bBLT zJ5Q2wA)s0N&YgXf+qC7uGSYe*{qW8)3T@hQ$=nK_-}wXu4tJW=!7BXX&R;==-!QQD zuvNeCPXF4Se;-AEQj2VTe<g=+1wPX5UJySmXatN^C4+T2}N2cm5MJ zvKd^YexXAG-ED6F#hw2ZO>D_|3Oo?n%Kwi$|0l|S zJ!vKg_P@*L-|C5o7n2THqyKyL!rN$-74t5#7O#He?bY98`S*mJz|`{>PjC%_4OUSgGRYZWq`%^kd?Va4Bndv%V*-|-$y{@t-@tzLV3^>36wpi$a7_?vI9{vpf% zggn?|AOG98SN}U1)Td>X&x-%S+pGTri@%xB8Y}uoZ?FCn7X2o!Ji;#T7YMENe|dZL z|6}R*DqfYcDsNv{{bw$q%D2+o9ai?wURYgX8J067LYA!HR{rA)tM^#`&7|Cl9$Z*` z%A)T|kxfhKp4IsIh1GwtR73L~TaAC|!s=gUjqk`NSmZAWzn%NlfAzxZ-;5QEs-_kG ztqZGvhZTOqavUlg*8RVGVf7DK_)RNhLo52b7gqm)v_tGz%pGTi|M0@<|19mSFlqOX zFRcElcQ~HGl8yK4@2vhg7JfG?l-t+V^Y6T~I>Q?ObY3Ie#J6g5@2sw}+IJADY351` zrL+q7-&t+3!naw0;N`_T@2vhMDHg%R#zIwV{rm5%{+lfRjqD1O75fd{3^}m#HvRXR)Ba_bP;9tMYGrWA#606`ZA@Qd`k~^^Mhk%px4a zT>7)}fAWph{}<&a|ZhirYzhLq0@37(kV0Od1TL08;4OP5#K) zmV7GG7Wr5@t@5>s`X>c8W25>~P@oy|t(pT$QHgcR*PN%xrwTSG-!mTP9IRZTkorbv z$6P9Z+dgqBN_2cwAqaFc0aYkSl)ozvDt}km$G;b;hkVCGg~ugb{6>N8Nxd>Nk30~#DS0=3`iI|o>#a){FCp{j(aT=v z$Z0+ut#{hhs+=mwt0F;l(}>V?UL}+xH&TZsXC& z9^T%0fVh7=GIY0t>@ymsal|kErvPi4-LSzeLh#TasNG`hk@#|cRBI#18be^Jl5k<# zO`Fyqj0`>W(SY>>VB>r62Jwqcd~y4 zBQcNAM=R?e-hZ@SyMFKE+DF&d)~?@M|M*8@%;Y@_W)^6Qjt6i@>xW2Z&a^un6>ua?KkJcXCf4JPN z)gEGfun=fJWNm5JJm|s*WPD!d{4uuEF1gE93?NjygK!2Is&;@fzMzBq#h|VIE}~{N z;2l>4k;hk%2Y{{E9VK4Me(&k=@zLVM#ETa%nokZ-n%&-$3G6-hy+83jp}~^CBg)Gi zOfqtjmpt%1kp4ye`YwJ&NPb<=e;l*`Rw+Co3)7eQk9WHJd~1l;1!~q6X~3?&h$~h0 z_FMgDUWgnG{bw)%BMJy8%OEb55^?OEKLGJebw-@c+vtP7N za8p=Rj$#0 z**`f(HW059l2u*22nF(PcZXL9HmLxrvg^OOSx}P zqdtLoPv9+k+&#w-c@KHvz_Rxw=#Kw+AAQg)h(0&jr^IxoA)HCJm#4=_xyDLj`plyF zjBesht`l5Du~5n0$>AXb9R(Fg$@-u|J2cr(6M9H&MY9@q8IcECR3_V)2fKiMJu;3(li zAzOkGTBaF~{`ta>fMbSS*$C;_soV7jE1;p|n2Q#Gu2$zy5qEynVX)|AJ-1KSC0jg8 zc0tkii>15UoBfj`QnNM!r?B6+c@Q?7eb-ULxK?HNeb`10T0^UBw|1U^PO*7`AQpx? z=s%GF*T)vzx(-Af7{Sh=yw46a085b*APjGn#VXYz&k;#-S$zxyZ@YnVlc#a z@9WFjY-M!P887@PI*~kp-_Xtod&3rLY4|efj_ZT+OG>Bnb+igVh^6{eVZ*H~Zt7AA zW2{QPu>-562((0Fd?hU0#3du3@c8U?o@~_DmscO$y}rJz4CJBEXD5TQe7M@UyAL+% zoC*$~owf)@{U$ljvj3@caT{hU8u^e(p&{)9IhJ&_zQ~FTOOjyZitW?V1`be%7#cYm z$Q56b#W(2;X*+fiP+Z4M!Y9(V+GmeJ*FsaA$hX(|WJ&o1nvsPR`<}}Co|-_7M-WdjsPHL7F~9U^|BJjU zyxD{EQvzh=Ak-%ey$wym-xFBJ6L?AUTFAvnymxZa+3mkyD()Qa zb+s^-;VAta!cl)hSo?qNVuj7!)Vupe$_3~>a>x)#fATbGTBi44HbncxTs>XDYvQ($wIJ@GBa*J9 zAFmy5#A_!qoc3|tJ%))R#(RXGR6t4kvPPjRt)LI#oow^|nmO7Xcxmh6ugN=JwqcMx z-dL1=p=D9Q3GC3H1O-9#$8PbjzvU^+AnwOnIrt$|wdjW|-T|HBMy#mWcGZo7kFLCw ziHex6`YS~^n4OQJLMcBm@i1B2tg7Gb@ukajII&;=NC+h=OWj^szkC12o%&;36xn$e zbtg`#jO~r;rc{~-uCuP4_9yZbWjz7jRJWl?qHUX!<|2O?e@xDuF}B~n^XKRT2^(mb zV5PrvXUaSv6*a^j`OU0LHAhx3L$Ju-Oj+dfN$|(N`2O2N4Uu0nNwHym%_I@1`lVYU z$tE9y@*Pp+H_}UWLq*Pu7geD^)`0`d5VZp{mukBp)@Vj$l?_Z?pzT!&-^GWjG_SS$ zM=(_4`rUZp=iN`TU8BV^-M)(#ugC0IfyUxNB&k?4 zgOH4@jtB?`Tgv^mVEuRk!{Om^lQwfKwqCTp2)hYvC{N92z+uJqfzQ&<)g)#nE z8!TDI@p1Cr_tEP`<^)u5q+1sxsGGCnI95}HOt+N3f|=he@36L)t@()=UyKzLQ1x`U zJsApGGVqOxLC7?;fz+hibK9$95H-g!`a2W6opI8>< zi7dJ|HhF)>=9}_VMSd5|-zByV`MFd>TS%9SxWdt={JjJ;+TCgOcE@$>D<_9UweiB| zGRPv@MbnA{@PY68Lkh{Ig>mbHSNFdqY77=&Gfr&MDv|tYra;@abo$=HJJfK)zV+vS zX?G8-cOfZs^T3D8x17Zme>$uhrGqxw0JqpeBvkn5aqZzlxm&UPIJokMStFP^8k-UR zqEUxwZScG=3?TeNiKP9(Ii1qGGy*Ppi-Xn^?+SMzcG~+^fD>5mNyX)Wzoob_E})nM z#iI@khIZx&5X2`zxlW|%#*#m;X`Y_r01Er^q zR|@(H12XKWq}o>X_oV#^-8|~C{K@sZD>pYmoi`t@udUp>eWj*fKDhg6`2jwxZ{EAU zy6l86#beG*k`v(H@-UgFE|I-cbxrPOR1k+Ci{?tf4gnOcq1`inGPAO`+uEtQ8#Hdk+u%;{+mdM04`MWB_ndh-S5&0(E(*0v|I-yc5 z5b}~ZpYEcbz}b2Zp@Z;8Jz6dW_|s{Ym*m}d-B=y_l)>J8*A>B`T}Ba#v>wKF(eEKW zO;6_jfx4OiP*N<21EX*w2x7`RkYx#)yV;W?J5e83_lWXIx$wz8WZ-shuc942{^Ke$ zm)nWhRsQ_!WE)O$5WjxC_P8)BF{l9UtF_Mra@XQblwqzF;r&fWQ<7%1QP(0momEuA zwsK1H-|}k^8hbSH%VlH$CYNVD_N6FtC-O3YvvhW_$Pv zGo}gGB#BDyo|-l?(o%eI{pRM~mDQE?&HHPc_ix>LxV#<~1lE{F`*J?tk&Q4BlNnvG zx3M@rrwK?PKOZXp(Uldh)E~h*V{aI6&15MN)t(KKP~b)^D4H^5*9t2XYcG|1HXEpx zcyCL(Ey#pNBjOS>v&K$%xoHUbqKE*Dx9mXurBBB~Q+4%>!Dn2@757v6z~e$L*13xa zZ4!yLv4I1YSK&$H{|~#76lxkPyk&&gr#c^nqd77stOPkuP)92nA*oI9VjIX%2qp`| zGuF%Vp+RF0-z{}$CF$j;W^!lkxA7!Hw*c&mmq+Q=kGK7^!x zPumzwo+pvK&KNi_W|Aq&EP9QQ0+e-1@Y2_wR1|AM;q?6~j52&a)@x{dMGOF2s)abX zqM8zB;rd!eSdP4auL|Zg7xz2Etku1Q6?zEnv$r z5rkhi*YZ;Lk zrxGiQ%QxGc9 zFXR0Xx7F$Qu?=E(9g{4M68$Ai!fClk3~HurjL)Q&SppwL4-Ici)+bjFz&D_VHmY=T z7y6wks`rzGomX~qd#aQXv_L>qPHEbsH&@0kmmP8=$;f9?7pQ!52@86{A7vc~dj96# z!7=3gveKin8bwYn^{MKeb@fH+cM4$;MvD99sF&ndG)_vrMo*|Q?eI7KNjVl0FEsKI$M}KyV0E|QOgyB8`{X;mjQQ$NJQ)}Q;aAit+rxtxwkJ+*?;0nAwK2^;kOOd zVdEgI2*YYqwyaTS>|xlcz8JVK*S-&12|RgJexb>E|8ce9%?fu~-q<>0kO-L^t)f}? zbu9Lpgbdw+??u^4Zb;zNFV(K^?lRh!qIB4r7u^#$f<-pn<$a$+7@2AG1I~p7W9#B9 zN;`I@yK#vjR` z_6jq?8z?v~KM~RKESTKgfZ?Ns|7#U4!Atn~HTXs7wO)IHj}bu%Vy7Twq7{Tf3EyeT z_S4AEP&rwL!i4}@#R&?3%839k)jr~*J7T!O^p0RMdePPtZyo`$dvc(`IkfPEbyLRci<#9 zeypbVrO6+Nt$t~GvfBD<-t7V)&D53&#-zK>TT=dp;PfPKKQSB{*8O-K;F_nrqj2%| zGqgNWk!xED5Q2mb<&O21z_mroa$?35)1z5KIhq|59g3+yp90NK4h~v9+;wHLP=pom zX;hw0k4J+0mTlmHX#^1&F(nV=%5Fo%CINPf`ZrN4J})dhL|`>DasA_75AOE*?_Cwo}8aq zn4W4~Ywu3&>`k}ZI}1~--KpvA1^l;tZL+;LGka}v+b;;Qb^24cI6HO~R=5`Iqe!rB z_u$3yQ|q^IkGna@&gFZI&JIuZaeF--$$zg0JmHvG{{VIMWN;vkTLE(^uQOGjqH1lk=04+jBEluTIZwxAu1CrrOhcz@EM7 z*ReRWZ+3CGGK({luW@lEXJ)PeMYi{_EPL&l*}b`)t2@&RIAF62J3G_c^H&$<=C@zZ z;>^6k#hF~6o>`olTb!GIor?pa)85(MzBW03_1fI_UTb@2etKbUdTwE%HFa%jx-~yL zbM4x~?(4vu={LSOvx{?AU*qD;w5O)p+w<32S7&yo=NE9EcD7ry+f(zCv#rU6S$xOp z%v@V|9g8#d<`!pio&d%;{!s;#MYLFNNPshBlX1%xAj8C)%NIn1vh zz2kZr|AlVxwJrWBjUivhBUMK+eZ}IDf}oYy=S}r}Q|5SP_Mjn3jIx@z%Dxm7q-bwB zzu8>{F;0?dl!xw)WCC`0BRC`2PjwBWjW zQ82@kIPoXf+4%(|%N8fMhp^0}x#H@jL1OmRW4ipZYk_oDnGpT`%Yc2kB@zzL!pK-D zBhBd}-i0+O&y91qB(_A=NNWe}7Sbm{L(}k4z(52PMl8=@Jheo zEAi3nWbxamR<44gP1fT|xLRI9t&U)rc6HP#pBp~kOh_6ViYX!%e7Ov2X zMW)%kBp5JhpA7~(TG4Ee)ozzsGw}rha%vX{{dpcS7%?1Ey1U_WyLoQa9~jLOTQ@YI zZ+sp1T(%?=I6~d*s+l<}w%}?*rZ9=Go1mdk?;`1dh0&y&|xH^C^%b zz0p(3mh%e1;{&2WIOdr=@5-ty74k@2Kdf%z!sf6{rqhy3i^(nuETnL5qN3GN?wv4* z0LDSu1cU1*<1Jwv5r@v_qYk^2jS$A&6o}3`drtZkfoHHVf;AZ+h@1sw2Fgt;8-)ma z0W~`()uYhOIh@_;6`^6C1`RS#S>ny*yUXj#WQs!q&$Z*C?*Yk)65g70G}IkIHH-hx zq!^K`hsB~R1VvF>Wj|2zn{qWT^F7FYNB9+;Yb$(Je0#v`A}=rZUgWZfP19a>V_rcO z$<&rFegMpvNjWXQ3FxW5{Q@&R{0cm4@FDb%xAcN<6M04BDKkF=leh8?;x7Dn?iky` z$F4Q96C`$h9BMhlE!^aU>!6FIa7s^1#1N2L`~9v#o}YHq4T(mr*8t70245eMM~Dnx z!62&7p!nZ|`)|X7FTM^Hv_QvEu1lSX14b^Oh<`RVpnIFK747DgSZdPSD{~ed{#TN@ zgssS^{$PzN)KB!Pk9x?5lu_xDlp(t{SjP&zM(RAUQ>L**QtsZ%D8xAJWAKi;JI%Yw zCsG-Ds2LY@f1R50p)LqSeAHfoxin(~rs4E7)6bx??cxP*3C9TeMl+Hb=D?6<>h?mX z!3`v_1b}Es22KS%P+i0(;>#0_e@4_lFI@Q*n3b6Kn)iqUKjB>}@le;c=<+o#ftxp; z&LY32L>6F^uDGV;L6Ki;b8n0{oPmsft<5EOUnxSru}yhh+FUsHUxG#x#{QLOJp+TN zUQx9PEA!=RH=6;LGwV6IrfxiRu*MSxDor}F)wT9P*W!XI7-`TCl5j6oinf&LNOlL9 zI}nh0*wv?E!x<&CWd>7mOZPexRd{F_*)W1G-H>UFDojPkqE6NABT~?cztYU=YZb*W zbwwx68zbXq;H_s;QLu>;K<@G2NhZ&VoRvcpPsUXsL*tJ=B);r7FdFqohtF`Fk}E_W z+aKgaQ&SB8wVQBAEQir6t5N4vd?JPWmE=RTv_ShA&VsJg##ApTGbC4*hFID-M2RTp zW4`X*C*IQ@b8}vR^?b&>VhCfyBQK*BP)Dz=+{7(_!O1ANFa@^g`KMw;@*`A=3?q+4 zhK)@VQi8@FaBqi+7?W#z_SZuErpdeDNMMlFHY>;yqI3#{E?!s{+f= zz@sjLzd@R^qlk84wM+;PDNX^ml!mD_Y}#4JeQ5ZYNs4ZN5%9tOEAIe-a6 zWcawbNXzX@I0czkSVpAL*~AFB=_W~ezUJ=d;V=VidB%9EQdwvbsKOtK*x)m1w!lK; znHG6^UbS&}-hsjK7y#roGLsOOF_fQ(%8i^`_6%1cEybILHNaSmxqV}-kDj1Yc^`CJ z$p@@-OV}YkA#Zc?0pX%U^jo=kSV&<=#WT^V-^2*u2h3WmU>3$ZH~4wy6Yqr%`HbZ` zxq4ZDP9{RC#Q!6(gkPPVL`}NfI>45+g%8#kQEXW$O>pxH;=~mh*%p?GG40nVW~}Ko zZL&M}HX9xE)5XoivExAJcC#=I0wm| z=pJg=8@9qmZ@EsycO(biH4fL8CUj~O0fwzi#3^8jt#H5BGhzlWN7#kN;k%k!s zxoMf=8Duqt1z1G1?-nFrB9`U;l&)Gx93e~JW#StT1g{}u@CgIBHKLNjD-x3hXFPg9 zZ5U*DhgWK`2L48fGH;hdz@ubGsd`r)=1`4o1%_m;7us1rrFQy=2A=c?EhSEz86Zk^ z)qJGSf3W&GRtfzwT3wcbu?m7{^1ut%P=fL7ft5Jty-pjmIumZAA~Jl(X6AM5puhYY#q|j16{fHHi58AE15bsNpxCOHz6c2lc zz_J_mE3Aba{Ehj){uru0=9-JUrit;W#vmb`SPDvs>7ozrEIZ+bsvx%q-J`NS9sg=%lvy9L3S3MnR)IUQ)shgSp~=Yh@VeeFkjf~vw}g%bMf>XH z7;41PUW#4~JbHebxq~TI-C_}j9pNPk9k5_}sLn(dyA{MF9nrK_mgrsNeNR;mZHdaY z-oObDn+g6@zD+S`;w1w^OYiKS@(hLYLxSjf2USW1)Gy_U)@Ve}g5`BSrpr)~!IN}| z2;yrENB!>pbH5oBmLe!dqbMHX)_*dy* z${j{Zuwqqh#R=+6bG|t{K861@+xyp=pUhv~ygFM}tk|$J@zz-Y8j|846MsdZGB&F7 zt4KeS=xV`&Q;~oM)%-*eZz}p8VZK9@!F-z2i!(^akBn!s^oQM6Z|CXjUHW0q0_3pF zHm^3P$LCK+f{Hb%UhiZ-2dV#szD8AJAuN5J<>yy9%TLG-3nM}CnKAWe~*9KDzq zJ}5@cu?J=051n8}Sw{3sqa!Uovq+tG9pE{?qE?ilbJdC|M&0-?33(U>9U#f;BFTB8 z;`vHl2@6b1zEQqG%g2Q&t<)>678?aPU%zU{?rr6UJG@zuKbPnSpwI?Ki{QMx%L&KR zXxaAJ#bAH5imU@n6l_}D_R*^r6lk*??HadrRSUmy%M)zR51FuP?jzXQlbrbPoFiSwv zc>Vs(`yhn!%6sbNn0T_^-F6>WR1HE)9c=Ru=MIM;Or@E84|PqvD_2enVr_fe8QmHs zhF7YQ^!vlKSx$_P7HdZvlZ6E9TszJH9U3p-ml8E7(aoFpZr#0q<4&F3?L5m#QqreC zT#efiqCmAX^H%I+cRP6qJFy%$pCBmvNSREM`$lbw*-O_IhpQ6rf*rXS|M5C=u2qtT zu!#X7!V?Og#stR@^Fw*lv~w;V-;R(TAZ!M4rJT(E%_N04lSq~jzP*tE{W#4IFZam8 zBu2^(A8QXzR(4v37Dcf0T3{Sezd##|4>^(*29@y+Py29(-et;dBgS>u`72K=T3Bvc z9U*mLM=T-A%aeob;fl1p4W8gG`+LhjS-T$ID|O}7aNi6nu(tG(-mJf;@uHzCgb7go z?r6v-o(Nrsgy=B@>Zf*U+>*SFyx53xK1ksKIl(rCXCe1V+H|#EYJCP+gl|~EEr}XH zREPl0<;;XqiCaMQ`LXj4n+GTBQzIYPGWLS*SOjIz#0~eYvyPIZtuM)Bl+Jp9DWU9( zCMBvn>A9+ecj(3+P&}G-IG220yUE(Dw*?FdHINS?W>uAJkc*%!|#U z%1lvdA39}{W^X$8BwIWCgFsKFI3<>rK^2oZPQxxUckag-eJ5YrBu{ob$K(5*ZCIZJ zcZ)cIJx}I3Gvanm<2BFHJC5x1OWn@rt*4z)XF7Fl#Hr%J%I3`IyV`6y+T-LeE%6YhuWi4)7DV&tuV{w%a4ZrXSVgs{6Mtz7z2J@(?uW`2);V@QD_|WnYVw{Eu;hH5jcWa;Nz}-2{uwmlk&BV)Q*7L9KW`a z9v#=dx;E0&kCng1E!G*BV(j9C*;>TX;(HCd%P#CL{TQwij;B}84BTYs0D!g|!japr zA=2TaC(mXbA11Fye6!x&dxLh-OdUryTfKeAT%-q!wF4h2xJsi3BhZy6C%*yZpyD^DLKd$f{oQo@MHd*Fp3 zwW~OO$pyh-aKXq^6Eq!eC68A!>olH1M4HgvlM`NIM^;fo%TdC`q%m~0(cgFUMM9&E zfd5Jr%L-pn-J7gkZ{BRy8tCK@ZoVCa?)|L(i*~PDYrh=dZMT0`mwOeh8nmYh9k%|o zd(b|@Z6liQo*o|`Elx}v?YCY|wsw)M>!7NI8w63Ms@PudWPdk$-F|=k!G7x)2lt@1 zw*Ihon`vc%N7rcyM}B~hTD?8o(yHp{7K{UDTXJC5%3WF0Rv7*oSk_kd>u zTYbfzk;>+KCg)+K2}^-0C>_Dwl92W-^Bn3Tnc(}tD9LiKN9PD~5l5n3@Phksk?sdb zsRcSY^d*Z2YxjR|`Nn$Du~@iRE<5T&V?Waul)~h3eNXl~dqb%Ji}$hQzj&jn*L)bo zji>CE_*_yLg%5ueZD~4*_zdV7>+&TZT$rr2w&6t;Zx1;N3cbgHoQJK86N=6= z8>@NP!s7J6XLwZ%0AXRf zaXKTBOPmgH%UgrX=-ar33l@Z{w>`QN_wgPzQ|R;uFjARC@TLuU;`X@37lAPDrzNJv zK62~x%ur8LzkAZ#;nb_Q4PD_us`jD!ql$WTj%^i6tr|Iylw z?%weWNGV9E)SIYS!QdlBc~x;D5?vSQh)57Gcb<0SZh`?? z)$~k4P>?!gv68<^wr_nbs&og}D2Wl|FEAJFfV;S_E{`}(1gG|2mFEl;N3M89oqZA; zdu~C6+~tcERGvvt`fv|(U;^6+gz3M8a9XK7C!rOC;tevEi90W+D!XO&f4amr`efiG45yup zg+FP8$h6${sj8H){#iuA%$AscNdkI-w8W0DP?hB%qPTiK04I){_KYkpU zq$K6WPFjYA7H>3=BB%Z?Ojxx1B1=%P>6V!E<12`SJ~yX!puQAt&B4C}PFcRKx@?syj-hNsiGk6R?mj`hO{*DP!JZa>5~0B0s>OB&80 zqR3SY(=fur)uv`>XQ1&3x3PD}sI&4O9@7)w>*8Gi$xIbik?U=I_O8? zIXc*2nFbjhgoD{RI5;^LFP92)z6Ki59&*FgP1J*Ni0R;H>}OU2JWboIJ?i5ok)*Wq z#s+gtFNbS>)0G&YJPq+mrclMbm% zQTlS~QZ9i6D9O1upB&MI#_1MmOQ_QC?+>nm_RrccH&1%|Rpd=XO$u)CN=>wncP5UW zbtZa82jgfqvG!nf{Pu&}<9C)n9#=9rK0QA^DDyyJ*3z?kvIY=Q%m9b>lb3)#xW@Q* zbGz4R9qzY~;SgxMI6qZsXLQ6ExH`vpOP*chipDsNZ{QElN|YBcU~L?NKGxx⋘TE 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 literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/intro.doctree b/f33-branch/.doctrees/intro.doctree new file mode 100644 index 0000000000000000000000000000000000000000..695b417a18df9d927dd854ae2f8cef6679757ae8 GIT binary patch literal 9140 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 aazL^|V#RBySZpHW6*P>L4I!t@^#22YKL0KN literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/livemedia-creator.doctree b/f33-branch/.doctrees/livemedia-creator.doctree new file mode 100644 index 0000000000000000000000000000000000000000..a44ec5a0bfb0af4920ab5a6bb95ea68bb36f71e9 GIT binary patch literal 170060 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 literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/lorax-composer.doctree b/f33-branch/.doctrees/lorax-composer.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8e694ef9d70ef065a953563edbbf1f27bc541ffb GIT binary patch literal 117777 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 L`Xpi3o6P?|8o32h literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/lorax.doctree b/f33-branch/.doctrees/lorax.doctree new file mode 100644 index 0000000000000000000000000000000000000000..bc096b53007a35f8b69b0f918bfcdf75764f6c75 GIT binary patch literal 81120 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

6vkuXQXO>j% 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 NEA15d1o=w!{{TuKqb2|V literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/modules.doctree b/f33-branch/.doctrees/modules.doctree new file mode 100644 index 0000000000000000000000000000000000000000..25540e66111119cb95d704fbe9409cdd5069a381 GIT binary patch literal 2568 zcmZ8j&1)Pt6nA3pr@gzj)AZ0dp_H~bY3*&Hhtf+aIU0N@r4UFE+L3l8tdXXY#$F!+ zZ6PHA-J<@vh5j^O-u1$;^Pb-K`@N_6v-j_Rqn+v(X08xYug@uC+A!{77&4QUIoCdZ zjL-jyZ{ukgS$gA4X)_+f4kR)m6|-E&H!)0;xR=VEH~Is|GcS$q)J0G9#o$dm6{FDe z(ks4k6n34>Vmij@-fw)J+}6x@vGNY}N1KvGO?`fLXZ$nlVcf^8bSC%i6Oc@5AuF_EyGx0-|Pf5+=#lv!exQCg^3sY*gkyxFx*ntm|dCNDGZq7~+yLg7oKgaV0o-gry zjps=iG|rF{(zde7&b6GBUXQD<2 zZL8LjP4SZU7}~q3nN1Yv(sl%!?z)DH7fJU)m}aF-U?U9>F2g~~shW;1IPSgFD@@B# z2mhrt+H+ta^na(SMBUr@5wpuMT5-)S^~R!aBSryTPxAuAe(i?9_7%u+LzY&7nxIl7 zK{lPjT`!gSHiqM+F6sRMcn0)VEGb};#*=5WO;4!MzD zkalq3u~BFy3CUYt80(4R*IWVdVJxWX$X+<&Yl&KU>Py!O^+J#FMY)2z=?%3SwSt7@ zGzVwoEzNjJD!va>sf*GRt~0|R6~n0X%d;QPoW%Rd_95Zc8cPJ#OaU}#9CFJrj5AaE zZ7aRXN(@i$o!m1a{tnaH=v@G<>dE%OJn_0)k21n{8THOx+aasqiTx`o7a_n)2dAx-$!MTUE$C)zpitwCDMer?Pd3BGz z54&7nN37p4tk(eM4k(hEN#NQOPwk3ht>D5vf+L{9<6{7|!QGSY=5V~lt*>FQVQtwF z{e*tp;NTAuvwjz^#VZ#^iQ#Vx6zgpiuP>c=hW}UMz=g?Xt19hDCb5Q+dswVFX`EWQ zI?PQ@Er;OIuzX=u*ZoTLlY7igdbDM6)OxLyj<@V%En1)U@Zrf@g0O2!k3N1o~a#nGrz^&@7Pt##w@L&W@6LTST4^0 E2Z+T0RsaA1 literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/product-images.doctree b/f33-branch/.doctrees/product-images.doctree new file mode 100644 index 0000000000000000000000000000000000000000..23e13a779f9ac55550fcf8e899ba89cb80c46ae4 GIT binary patch literal 7068 zcmeHM%ZnVx8DBkSS3BB=9?_aulBt;3NU~-o2O%pW1d^PL5@BQ|=wftA5PPN|t1!gE3lmcBjAks=oK5zW#mh zFMqzg5q|u>Eu_llL!KnLPK2%enMB8BCURGOUS0n~^;vbzZySDOb!lQz`3+#iQl*Iz zdG%@K_Xypo)DD~dTUNwQ>Ac%6dva55eOg_U+rHGVS}CvIMd`=koIg4jjBS#WUYDtW$~aNp<788sM!-U6&MobB(^jnV4XsMF>^0M5KC*&!=+3Mv7qf{F{9~eD?M(n7l z#Tuv}%FtL>`O~S&MRo6FIe}E$V3N-aFXW0k9{u&?#>Ow{AeQSRX3L_`##t5{!AYr1 zPg!&FP-U~Aw6a!O{cIVIb%f@mV3QJt>SIGJtR1q4Qdvg7S&<4du}D~HRXz*IDz}cO zDIMzsFklH5>ntO~97z>RcBIm@@A#nz__4+TIhX@6&Jtx{cWoAdr@*fO7zY#v#6gK0 z_|0R%rbcH>Ibuijm)o+^IyM1G5*6r^1=G1`B`IJC@(I>(84&uW%$>@_paBjY*k;<$ z-U7BI$;RVByIdU3Ec*%mk`aG89y6y|FdE~oJ!;5^EjGV%`z9-jIQ+SND}^Y~0w)n} z-|Ez38T5rC^dXyS(;t=AjI4z3)xOaBz$k2fX0@@~s8gK^;*oCqjX*4xMr%jv2Me_m zG}fA`oTsfem@`5Q*+;?Z2F&6!#THUm-$`x78j)IPvSy=gcmyf8Ww>>%5rk@1R-7z^ z*^FW1^Jq(F=D^*Syp01=_fB6MzqAo)R{;jV_BulHI z&Rv#2M$M5|P&VZ|s9p@8ck%flKJTN5$ZPV$hLeLwA0mL>B%yDXgqET5MvI{^f3s8` zfLiipzlTPo$LLZ85M{Bm>(31>|S zscQ`z45-j4gASo-Be1g{>q4Ql>&L=`9>eLP?EpeOTUfLvDA#O4Wszz>vl^IyEOg0Y z&`S*VpzPK44<#P0Ed?3c0wd7X#KhIYq3fNY!3b2AM-SUz|E`JEg^PR$Gd_4(j%sb* zHM(my|M$;Yn@Vn(6|fe1k)T^!8$-eVXp1cMMXlj)23=E6N5GXXwoff-&PM3wMor_> zbs~&?q65B|bLv`gNNrJAy1@-?Jb_!T`s4~nx=a&Rl)*9JWpGKfoi(l$M%-;J{oN2| zY2OL#JAPIBUVLs$KOB#r=~f$iJ6tyW?UJZU{rVRfH>~FvAD+RqN+;qZFpLCN2Tqf15;Kn*LkH z7rf>PQfTM>{`@mmYV*4V5A8ksd5VhHxt*Q9Q&CU1~bC;VPq8XDhgo4owCg z&emiioPCJLe)CwG6i>TO#}N$%X%*yp;LE_XE=%qt;0I$6vGqZF-Iih-i2(bu`5_oV#?>!JUCs z_B1VQG69vE@|FE4k_S zcde?Oz5K3 zoxw$77d=*1)&993CCc(iN`f?8Zne=MZ}=SuW8wc{N{mBy8?-328evdhh$5maggC-D z7&u7W1$-5x$+10?&K36VXmoURgpLhk!+faCY?O${BVgK5MlDX27aa!Z8ff8;S$Viu^AhGTE1pc2mS=~G1ufm(Ms0*x){m7!# z63Cthfg9WegrWI3oR)Nyz>Ck~rA7CMs5@sD=*i}hR5O|46Xx-n+Uk`Y}p%%rQtM4PK2g+vPFrTgMbEM#(3_?!&SGGxRPbyx?eJ{VAM8$10z~)NSxz zpmbo%$vWOSkxfK`cwB&%6iE3`{iQh7{4f$IDrtnCFO1QNzf&TAT-`4x{!E<)5O?q* zg(6HN_^7TKf#dTa1g~&-K?B_+^djRkB&s!N{jvjKoHp$qsM67U62P|zSbvva$}g-D{rQ>HcD;vI#V2?FAUP@_aW1Xf@EL4bWzx9g-{yBty pQazwvfE&aR-XGcU)(Wg&=wf~ie6|Azll2oyLrug|X)Gth{{tbhZLI(R literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/pylorax.api.doctree b/f33-branch/.doctrees/pylorax.api.doctree new file mode 100644 index 0000000000000000000000000000000000000000..2d2d5f94c3136f84ad5b0e98a61733bbb1992792 GIT binary patch literal 1004255 zcmeFa37lLw)jF$k#bgkZ)X;+(zw=Kr&k-S@PbSC8ct2))`ZoSpi zuh&-8R@PSCwpgyMiC1*%-A2_aiZ{$3ZnWAJ;9$O9ny*anuk5QXA~{emzp;7<+2Dzu zwMg7S^&8@q^A+HyyI4DJVX6|3RJz@EeQKc#?Lq#R)n_`$>#FHSrPG0j@b`*lWlsFH zdS+qX{Fnk3+SOU4S%_D4EBml$v35*tw6?Ccw6-i>sU&gg4q|+JyR`#k(Ai-%WTM^a zF2>6n^=5VP+M^bxYHNigl_+Y*s^9U*4GU9qt(k=eFhkAW=sYrwJQq0F0j;ZTh9=cc z1p$@dzb)|JnegA)z;3NfY>p$FwXxc^+Bw&*uwRHrI_6sy^?Kr|RoRGYv#BiEkh0a1 zlWhS^)zJ(}qGhUKITWUykA$y2!e(1Bnr!ElRy$XNjF-eK>dl$zA}dV4Y6BzV5Kly1&qe6lFq&Xm+SAHLc7U<( z5F(nGKfDXg2l#02E45~s&rZ~vomRU$*{IHfg`acnQfTZg%76+rab*WS0{t%@x2i0U zmCE&|R2B32vBmh*bbDQd(oOv+sD#p}EGc4vdAMsMYiBYNy&hP^Iqu2k`FGgxL?nvV?TkP@|JAUTcX@wbXg$ zw(#z}7S>)^qvpKWG^h5W+BxF$52DY*cn%`(R@;p_45gOjPsvrC)|@Z|U5j1A(u&}J zNqn@jmdRvm70t#N{&HLP7s-~zOPh<8h=ThJJ5X;M_Q*_qMkA++6Gt^#ihcakWxm8PUt?7fZ6?y%zZ$d4lzTM6R2!jBnKC|*y{tJ}0p+H0(U2P0 z^v(p&mvEIIm#o|?W%=1&1iebm1Zi2<>RQ(Drz`857``)P{a7Lmll3%HZMLjM&91Dy zCVmI^i5?^_J{~M_Kj9mov&ae0%n-|4&BkGCfRHW_OxN?(<_vf^lZU{APZ2mWk?(Ab zS3gns^S33G`C>*S@zDqB)q~T3leWVsvfu6Xrh7*(WZt#M{&*Ge*F8Ls^Si2X5l~ij zcBVB~sW%tnWu5NKV!RffR1eKJ>eKb^;+;g$t+e-50b7htO3=W#lmKqv#rn)*?Pc*w zs&pFavRpWve4{@BCZTUW&&TU>-~im><+biygI zSxiXR2$&^Qwpd#kuby3KGz8vy89LHW0pJ0C!L>`l3Z9H^4^0-rDVuIJyEaHw&Xz!=>Rjni30z+EElS`|RGKs33s&c$sDz$&b*2P3abXTU z@=B@Rkq;+S*B?MldgO?{AoTD#j~-BEpFz^G+Cd?b=u`MpNM%htGFz`UW+oHvk}z{Z z-c)YM!xYI^lRnVMb;<`b$kckITL2Y}M&Aiw|9<3mH2P=L3Yb?xUGn==tr@0QuZh=A zfmKui{F(H%JM-1)`fPoA@!6=!)$j_4VmZADbKp^>a$@`uMbTXr z|DweJOO91+R_Eqxl}^25GYU}$@R%j9;)koMEgp7}zmnkZ6c4F0W*s$uI5lMHfiC(O zG{hdkqBEiH=p^_b5{Mj)v_O`QvGM>>El1^L6|R-tmt>%u9XpSu+-39tIuqayYy3(_ zRYboVjh1?(fr9%j8uw`QYxrkjDp~?>DC-m2a}9Fap;Eau6+xtgOp->XZVQGcF;F$( z?{2M1;}mJM9Idfx)JP$X3!*1_cr}ujrg#gzz?z~cVoWhQ-R5ScXo)gC^;2ts#))|k zUzYLBc}Q*Ji!KD>(&`5Y%nNAWc_`A!WL{gfm@TI9^Dv zS}t+1_rSFAi^Wa*wH|q=eivv}3@RR~cwwQr?=Yw42JEnAlFTwv3sW3>cGrF)2z&o8X6ag)#K6fG|utW}}& zVxOhq>tF@@FwQ?!01&tivoQ{!)J%sEgB=`?yoz-SF$3qTfjr;Q=(qr3NR6Q|2CT8Q zLSrRDZc;SPGc5$t+=By{m73du(h!b)h~}2naj6S*!whbqE-H3;x!S`^9|My3TxvwR z-19}WTdCED2armwqM! z*jQ<*wE(CTsv7A4{;y)a75vatwbZFr+S9e_jK-r6Tn4ojMjg-`i29BIU0X1Bou!?m zTAqJn4RnHP!L=*ERsh=%RNEbpHA+ja%7B*C+8Ic*(k)F_n&i1uM%2V#nr*d7Y0{Gs z0fDv{o~b~Ll=H1l9W^P3%zAgk9xSys9&mgaB|JkY;c3N`aIB+*{2uiQ>QN$E1Kmli z>bS3vukOT&8|OsNRd5@2PIo<=VR_TyE}mRRk@xO(jn%_X?(N~5TQ z=*qQftX7`4!@}!!VHw+HP^zldmo*WlBFN~JTEMQTSQdUPxh{^2&xr+odtKaFJcWKc zy&uC>{a;>Tw%lw0rTu9n+$*57?Cnb$h;xmI1-YvmRZESR5R2Rf~y3F~i&cv=|) zmMla_wRSk+KGvS99>g20YRcV(c}N~ni`LK7L?>nOpxnA_0&Q#L$b8*nXllUgjrz+gh4jTo%^I%r*esel zk2l8Zr_0@v<&4MAFWLP%upzL>9Q}JBEiAdPjgFq1#uMr2WU)n-64TV^HSis0dO%lE zESyHCFfTZvRul7iD^%mSwfEqIoF$bKyQE@UmReVdeh9MEODoZRP%-i-vG^t*k77k7 zdcS;4tfyEqPcErMUxv@6R#l>pV0%u?=;VtOaILM3J`PmGFV0-Bpdzgp*HogfK)pCK zfM@kdAX7#yz+&e5G&WUC^ST0EtuyiB#2RB%*wJS6Quu0gBM2#a8H&+_TcTHB$>Xr( zmGGB6v5V1hEGe0C^iixrO`SBmTMA20@rshBc#Bfa#kuo5&YU^({3b^gb2FG|pz4)# zd>)A&1fp4x0BC2%V@Ie^oZl-*Zszxs`k3EG+4)^GMQ6sjbGs~b=Q6`m{KTAjUA&t= zr%M`2wVXr;y#=v}N${ZHpMGcd3)xz8=6Jyj%q60`h~lMK#~IWEMBEVt#f z8*x0>R5i)+h1!(KeRzq-j&1khh1!;fZ8)w2aRMt1)yj-gx0!DUY$iGtrkT;7Vv7?_ z#ZgiXnM1G=8P3&QUBj5GKgP5#cdq^`=7mAc)tmXbS`J2fo_-UskU39((8nJ?PaAnB zXQSx3P-DhC?IeXxOFo@B8hKT7v@i;qqhA1zGv{bGPBpILlMu_@)80o({IFmT10_W` z$i%m+AynCRv6r;TM?XcrMx&n~*ZE25GHoGxKE6T89MKPTqw>SP(#=pZ05?N-7dNJm zzHLU`fi&py7E;vg$Z9<>;xvbgX7@;c5syrriuhCEN@_rCfnr7Xv5nU>8G7 zhN@oH#c)ZC_D+J-Y>e}XjL;t02|9tX0}ypWfer+&GBELrzSi(xsK@i5;C9tW57vW8Mz4*foOL zPAXV$-Yy@kcWdwsiu!ijl{z@_`$`l0J7cA}N*4e_he~kU2rUE1nkO-`uLHop8_XJY z-6Yg?gI`^0D3@xn}1gvK6s5dcb5nvrb>1lyP?HCx?Mt#Y6WD<6kT3++Y;g759> ze5)k);*6t&A+z9Mz0ttc4p1=W<8@0@3$W{Kq+6e>PL#0bv*d0uNY4{H&PwtN@Dfx} zg1ug-M^K;$=pTe#Yq-csD*%{22$`0k)#eQ5n;#z0wY95vEY#cZ&8fpwk7aVO=mQyo ziFV+(w5gm08K}VZbcK>5VD&~;TiSc&&DZbgm{!eWt}1*4mUN&_)w~ilPtMK%BSTCu z=~aftzNdwKR|?zrnr!=y|J?5S$|i(emuPIE@d8H=v=7}2gee*;>Qu#8(`+56!-fG^ zt?E`94X_%y{iOq=URB!3zG@RUM+obNQAoVdSE9fVjz4Ah!~vhz-Z}~ zq^nAV3)JXZlcBFXM1M-Uw({&ajIGo4`Kk}sONJCGaB;mV)Jh;+f0suC3Z&w)!1GXP zG{wh{8;G}t8L0|>h>RAl$Zg$g16zl1-n1@y4K_3Z=htX0ka)}XUawgp zakE6QR6c>6&e=qk>$^FY_=SP{I8uJcSM&~|wU~lE186cy&YZ`vcp<4=v3-I2Fwf&> zIMQ4mUCd|45|piBK!nrAFajb!VffDti2RUw!ES`v77`U+yvPWMh@PuAgha0c7BT}O z-}CXu2Skj#Qvs1Xp~j$qh~(1=h#;>jAR@XI1w{TB9%lwb$}W5>?*Vk+j@2qzN6*Nm zS#S&0xEKC{Hv4GvN?>R-+64c2u(X18!yE!hMkgXmFx-Mu{*BbaPT8NESZM3Vj(~>C zJhyS=YfKK3*MhjXB*kAb9QzXKx6eW%J$Tfl%#xK-@2Xjrh+#O9OP@XNKGM@bllvx< zlCPo{*ra4p#N_R{x%9^-8>0*~U7!t-Cgn*Fuef+8H+S6XA+;AzDZZ9mJT+^rsm&b~ zsN0A|E{tliq>_|%374d-3s2ycsRa;c5J2a|I)wj`9HUhBkCosfy6I?ixko@KOS#|U z;Y8})@3BeDnWggeG{f44%GsovVr6Jg{nQO6jor+2IF3>YW{&4SjhVn`2ox8vPdQCGa6S zfBu?-RN1cs_?E&&z6UJal@NNwgNjtozh3-w`_w6`{2qrC?Is`v(UwsX=cFdy_>$`v znizSyvfYMgT%A&wVN(F6w^mB??bcKSw#*)EL-s4iGeowt9*l`e$M1@^aS|u zU{U30v?HL+q(R--)iC^@6Y!Q)CQ2$una&5W(+Gzvzvs$?bLF2YSfBrrTm@5(ukIqw z`V`J%G#WC=HaJM~$u>`b)}~j%DC(dh4!z}ycH;A@~)-h4xq5&1yr+Ul(4`oz_e2F|#BO$AevO!u8k=*%!Ech8wEHQI*o!=%)(ZHKJc3 z)1%QZu}NX6Ep>cDq_+IRv^X7l@q5*UA}>d;_H!s5z!4w?$3Zd*?HW|%H?)rBW!sZNU^&Ln}}g7pZ`LK<1h zJGDno3mc#A5tN0EPbE@sl;tXCo^)+fjTn%}(JIMNBsr?618mU_5;mKdPNk(Jo@#-S z%^dKw&nQw_ahqOXtymQGYsG);;mES$XM0F(D~_%Q;sUXl=K{HDytHE7_>>jv63&Ws z;SRLoB1+cEiVMFAR*&E9$?97k!KSP}+nqvE84(%{s8!-zoDhO=?r5|spjHWN)$FII z8W;tf&_I0GO?U<^95buq2iOxK#xPy&h~z4oP+(gx`T znl{hq??4M+abF2gh75qn$sPkBN-sW*%TR-I+dz#POSuL}ot+6aTo3H=p@tu0Nh;x1 zgc{70(Q{hHgq@EQ5@~QwI+iaxm1GAQt{+U0!RA;dFXY4*HreE5^#c=rh7eO&u_oWM zR1gkh3QK`j#uSDp7!yudr<#sAm#XW!4|S)Z3HbQHwqOv!v?bbr%}N9j^k-1);@f7= zCsSz9Ia9bXb|1Q2Z{xV;vH95?X$Cgm5=e{KoD;?{u=yhyo^rAI)yxaFcX*)ujrUcpHqY%Z*tu=#JG&QNTAxm@g_Ng0v~aUp-DAJ)cB6NM)p9EdhJn zfl8tt_n}q@jk&M#wAJ|i67;-`USL6wDC!sV+~?s4?L#I;-0LB=K~GWW{!XadG+u%p z-S`yf(Ip({(S>Is=<%u91g+yRdgxU61qpA2En2@_oACo9B43Wuv-6M5W(ASV3o-NlswPyp}^GBnX1bjo{BkY1cZ&{xB_6GsA zN_?co8{N56_~>hNsu68|5GN493hYcBu2O*>+@gb|5E;RK0m?6@@pzBB*H2O5sYZ?Z zf$Cg!re4`jUB10T~Z$M1Tcn-wUJ#M^a%R51%PZ5~=05=V5Dy600z;eY{ld zPQ#g2K-ks{sl6JIN{6ru_Eo^%iQ5sdsV&>e4$9EQKmFgPiN=KgJ2eVjzY(29?bQm?R>VaR;9!Zv zywtW}d5aG?G}ac-jtDb@`%`bj!Zg4r)kz0dpYAl#eb}7Q=+CgRVJp!O#Ww`DeY=r` z0~N2k5&b^1kGg{huqv=1x_>$@PWu??MDHC7o%Rl~mzqwIP!m#n$F1A;>mb}fD_(*X zYe~cdty?fX8hxm+T$h11vgG>wYbbB>F!|Oq^-hJBAmF%A6zcQ>tWq>#qc5D?iVu|W z;Q6IucV-D*uQur=+GY#|H?|k56C>4q6Qw7Xw^SPSsmfGk%ebH)8!wf&!1b8tZ^!*B zox>g2_zq?G3KYS*JDl7s*0CROd}*ylUqllfjXqyk4=Wr!xbB-hY9jWNexDi|!0*#j zpZj9gAtLt!d%WNGJuJyu(-2(|5p%D8--T-HQgw2FXHuPP5VE-8o=+wBZ?d&z`+<2U zcgY&_?yi)M%tXdled(0j*!Rko9EP~Hb;;WN0oV2re~mUQwzeJti5XAv1Xe(*(`S_G zu1C=9n80SD=V+Q4t%ui=p5q2aF~p0VUb)sH5{w!*GF`SYcAmMcpT)7xyOO7Kq#3T{ zDMV}KT&g`cG?p4}oyS>wVRv&M=6QT5N1Dr{J9OD&o-$5!cR8&M!`;1&;Xl{ieFF1> z-H0RL?j8p$WV*Yz`1s@9T_f+5yZZ|mCwg{wkyqvJitb15?l0xo1EHGq0iKEU%8AS6 znFS)qXS_T$uh3ESGUiy2x^_kB@-KOz!eMUDvwLYUuxb+!bxDgQ-qerciIEw=M z57r|53)w%wqs$)sb#EGt?)8WXN#*v{dx+GVSUHUCt1H&!yIMvW(h`@_3#=uIBCjPT zHmb_rl6b0hL;YowhfB*kPxO%5)){>h1YaO!ax>Iz1R||d3nXQox`eY%Q5a-NzbR@- z`L)Vq#kU01Di`B$*!5YxT#S2hK&^5yPR%iTKu;~k?cXy$-#E;iAW=O8mn_m|NOjyC zz#TkG48lXO>;?zVl;j;RuyO_ub@6Z{B3N8-1S|f$u6H<6`VJYBoUB<5RM-&<2QSLBw zXpK?b7iqv{miBNQ=0iM-z<6eeM>wqggm@-q;S{%naOB%0910u~*Ui!$-EGL}cwb;! zFg#=061^9jl~~w=i;ZzBvJ$*N5LTGO+KXj^9M(gA%H+C}f7xzUw_ANmP#?4Zx?E$Dl?I8b-u` z0)R`bGt)D#1|R*(3T? z=g9W8kW@yNZVISXMwW2K2#hT438+;@melm9=b}_(>4CV{RQB=*B5T@Sqhr^Dsf|YK z;h(^iDCrGgoJ#4%r*RoiP(B@~QG+Vi0BJa2;t4U>3Lj4>1LK+T1U<9#oHBC3zG`<; z#)l@=;2#oKD03OZTxHqug(nOqahU(8H_pJlRu<=N4k6BPsmJ~l^20d8#b~l3&M0d?CIe;Q!llh#59lK5$5lSlIPHV zDL@9&mqi))JR7-6`j*yK9@pv%RFC1kRlbkB!E;Z7G+gPv96P9kNn7h1SzT$ zYb~Te%Aem-gCq5uEj@yXi@T<(@U&BHz^OYhnjNgdf@5=QmsTKgb2%=4!`)tV^A`Tb zC0w2SGSX?maMxXEH-V-Ei|5_L@_0Xah0#Gc_gGO_y%H|(g2Z{X&vb#}r|@kEmyTfl zDk7p6e}5NQ*L^8EA8Z2#jRyyqh&rnR-aL~d&44#gCt7Q5)!M8{@gKur zvLt6?=W93)cxGS0k%lts9yyZWmnqCYV(C2`D?HbK!I9>2?GB;#6s-CUB1q24hJhge zp5Z?iLH;fCg58KCuqfOG7BUg!mwo*42-3(qg&-dfHTH}kkynKv#c)9g@>X~piXeAN zSDR)CINWf0KU^`auYW`wiH?r7Z&QtV#b4ATO|;@zax|8~KS6k8EP5g~Nua>u&IaP<_tLQl5eS!JdX0 zj3F1#Cg=rr@k|sk_{hCoYPD*DG9mLon+8poS9^FvG$E7nukeuefwiJ*pl%}uxrnC4 zkXl63CEOyKE<7fwI^Fa*RRkk7z9&2!*#*FX%^u?|oOg~#Fi0xbf6GMbUH`pE`+#Pr z$aNJ=91&ov+nO&mst2kK;Vi<+FdmQ!cN`19#N9YjV3vQnrzJ*3(o%nqUSKU%6nQOG zV}2gszsSRpWuJF>NNxL!ZUy23i@YxZa?^NepStlW`_v_zed@xq!c=OkHt+?oW&B1@ zwtUzl#NxJmnSI`gF=x!vaF3xf$JUvX3anUZzX#TR&eJlZUTNE(rWaV-7DfHq_CI?# zvTXbRcu4!P?QcQdrt#9Yb>maEtxGuD)`jDR^lMDK*n42<_{E+q{SzLMrYt>wE|7@{ zX9d(MV}9tw_+}Ux%sq}s{lQ!vWtR*6`nMJ^P5R~I{LY~Cw9W!juczfi-Nzp#6O*Ka zE6*4y)0OG1CZ6KmY;{X}ue|yCJtC$7U98wkx-|vg19N#Owue?~%_JWbrN1CRW>T>z zvjHpCiO5UkI?uF7NWr%RFe?>&BMQXlN;?XMr16eO%wh&W(4{DM8ESYK>SO$p-%E{P zHP0upf6G99HGov=7R6OaxA~)n4Ad)}r4^A1)PMDIal8!dRfDiQ9NE)>MMn4`HU;5f zjCc^__Id{bh_G1-PJf;0lqPoIL;9cX^(Gu;)M!j}=jI!j7C0gg#**LXDrpKaC(2M1ZVQ&Wr8@-%RO`*INcwD z{BY^up^GjcRun$@Z`(fI52CxlbYKK}ae%SOkiSIY>)a%oCEL_o`muDV$j2TV5L1^Ojg*9=kqlx^kEf-%@fC##_jxxJ1 z5*A?=Uv7m-pI?0WATXY}_#%v^pT(C8G4if*s3FBnoCO||V#Xdy#MYL%6eFT`wVZ1b zPGKt?ULx36JZ7Szy_g90MYJrD2sWUjg4o8&!#2%g$q5-`;(V}-Qr#iQXZXK?&BUb> z)6D3fvBim{la&^1vlb$p$7U76d7PCC_DhaCK9c`)jx-~Z|IqpoLNm*unv; z!3o0n12aDgU{VeR~ri%7$oFVo`lw3Y9Wy%$v{37Fc0}I z0zG9xKEYbgxpwCvc5p6K4S{-RWu@CWHT41WPENBWCgUL_!tM3+0vqBz5@^LB72h(r ztigoT2v8Y#cU(#qYMfpC2FJgjSRq#3Yoe;_TwIf zfORiqc*=!!FJNAmMu z9!sR+-Qu%78`g>bsqT|LP-!gaTLB8brMqYJVPtJI`XDkMvQ=bkm;(+8>-|PpJ?;7_ zl<)O70qvH)&=--fF*zs&!Mb4_WcghW!^YE*VD4M=0t@Cu5#y)z4d(vS!zFq*63qRF zhtzidih{Y{Lfu9n63l6Vq`;gm;lP|I%y-zN$M{W8lPpk%MiuBWevU{72FlJm-rwV; zLQk}Nr`66~H+56@LNTp&?R)rLs z-~A z)@;P))YS)O8|7FV8fyC}nNW6+$VP1+0$PdM9zRIbmXKTmw{2kLp@v|#Opm-2ocVHK z0};EK21Z}PwhkY=eV5~o$8O)^NHeh8KLyevcHv{hF3a8K zVcqyZ63IQDUSN@&C}RA#zL8wp!zG%QL~<<;sqGaOMRHxJ+XzG=IW3SBlG7y|lGBCu z0-Wws$z?gDw!uZd3n+cin?0gHsYxFc%`(sjy^Kf)h5+vgU{dy-w*YCezOxCJJk4lF z4x&7QK{+3JBt{*1R50{?5IHM~{oWtYa;Y9{`GD0^5c_>2fLW=guc0ss4ROV>-%ma4 z*u6aZBOvY@`~ArCMLoNXM&A!0m5N1K6;f<|$CuboO@4*2pK>v@>eAQ`1<7DPe9U9N zts94i{dORrXjGc}7I5ou2l#A=0#=LNZaot{EArsgAo{v8s*BN=IaNYS(W6!t_d4(y0*5ris5=^-O9!r?w zU6b44#dUi8ae!Un_jDJH-hu3mM)x4|Ve4{38fZvZZ!y9e{+irJ0@^Gco(~~kV{%Y> z0ARYWdRR9QMq;|Zp%++8CyIuF>3-9(HeA1`FzITJ{W^_`P2XoZ{W)MzIG zoxU(6n?Mh2aW)MMcNZZ~MbX?t0@^H{er)rA6;lw+-5kKIRL~75j6#E3FS}y*dl<5N zc(fFV3*b4yPpXga^L)|*bTa{@Qnx6sLb}cG^%BsjnXeF_Q@(}PUK-G$BpE=5k9k1% zS}YmPV%`Lz2X!=U2%ckahqEi`1J2Qr;hLGDp}BXHwS=wP-3PQ1%?;=VH&<2(Ft^Sv z65mgwWytl>ksZ*bi4Q10(J(hMl~l|WjAa$KW_0p)(p@RSSX ze#yLWgrVH0fQ3vb_X{6?Jd`u?PC>c1LybK{IpkGAIbpqoPVR-rp-}FeY$&G&og%yD z((mZ58I7F;Y>h@+;h#VVH=NOhWOODnbEH<~E(vI|baEbwe2vMm=mCJ>9_wMZeI*wR_f(*D3wBES}(ii?)NZcckJkY0dW!FM!WP< zUHhA!Pg=VD#{g2PTNGCz-R5_83Eb3#R|vQ%PeN-i4ct(Y3~=u&L)@ZsLg9Ctk2yPhM>fO~rbX%X&mjUEQvJHYUi3->zA3r864T?Q;< z!o7JPe>~hX@=n3MGSt{J+(TYrN}-iIVZ8)pw!vcwWxOkQTeIPw>SlDMt;$IXrq^9E zdL6Pe8od^o4O^)j;Nd8$5qj{40f&V2DkG%fuh_jSpzYE(x)1pplY>zZ-W$d)y3cqR zHlB|}d7q>gSd=G=o@AcC1Hvnld%lB-26D~tOkshY}yXdwee*sv| zfpBLAv|lO-+dp6>6@+kC1~4m?br}ky&@j~tgnNRAA-mT`KL^Y0AHv=2`J@HmZU`Wi zxxKPfpLx^t|?FSCR?X z;sJ%1-H#EX$T=xF;R(hZpR&%DgK{_B zhkCFknD?&0wjj(iZHeBA%}T($b+*{)+xE3#uu9*Q2T7O%F|CJmnl@0l?0uGFkH>kR z;z%=a-p7d6KCn|5i;$S%Z>9Yh4(yaaT^_&1eVFI*pE%N79^Bz*$D=ms8 z7ocv_c!?!-<5O5tmvC587oOnkHPedIog&U4fPR8?2q!@HgOs;ukBPe1j7GP3goLE> zzO5UH)N71qsYA})`-!wcT4O`v6xh}3P32aY2U-T?QoPN>w9$+-%Qw*rtXYbpe$Dc) zJRDhO`9TkcS0^}zw0KtqEP?yG4XrEALmUS@vt5ofmsxi#vAs5BWeCSPEe!*X-_7u! z3&&r?ykIxt2pqKfC}1HIj^E|ukB8$%-YGbKF4WjF97kTkNui}-(cK7+pAU~Efb}m8 zTW}mLHU-5UgWni$4W-vcAAKCz8I3-Q%mytDN9W-i0*rsyv?aZQJ76&W)c_7982<{g zHKrIHAQ(R_4aP|=8qXojPaq%f`1miLh8d?{BAy@93oPOhMg1b4Rj2rkK?3pR9#R|e z6b0gIpl;K6iFkD5Q;0{GaEM129*2m>RhsS$F;fVA1K*WsN7#NS0RMqUvliOd61YYkbNxzk*Q40(n6N|xx#a~6=7AOg`4kWLDAg!MTI4140&9_?$ZL_%OUz+o z;)l!AO&*?5meMA#_mJ8)8EppQ0x0|zAUDmIHmRGRvPoUS*`zL{*iTx8S^y$AlqLY% z#5#Ji&4+q~l(Nli=LJb662Cvd;w2KtLE4AQ_L*yEA-d$1&9cdGOiz*u@l z;up-d4pb-ACGPV2&ydyfGKb2!$}$nU@LTilf;^k6uRJ}wZyfG?qKir=XX@=C!0XR@ ztVIDIgx7x!v=UxFVK5;FuGOh@=i_-Qk-Eee>P|t^Ug*VE=l|bWa_Prn^wZ5bv(u zdq(s>^fb>P6baCNpI%@Anke!Dv=P$~F}81v?MK@7XhwXwhd(qt3D)lRklJ9aXaM1r zP`43<1Z!FpDX^wXIIyM*H*hM{&5zk)=!^KiaBh;rTh7&)PxA-|_P(W*W%rGLfK7NaO>vtOhaSeq3^UYqsg zn|#m1k!7Xd_K@0E8r=)T1wslx0CLlKX{EaHDJ#__oR#Xr)BP$nHXA?;7L0Wlw&2fs z1edblZ08I~Wtib`K&>*&fWx~FbjmP8HK0}*W>9lkp|o%1a_HG66-Ok~VLs6wi#2>PKE1w6Ib@etE$azyAJ*d#IS3fc)VSmZ%uYvlly}X&^?ud zv8IYl@ETt?7_4W1%D2FLk|8d)$4d+C#_p}~KU;?YfNuf?(J`hfi9e&p@kM~+K=B;L?jn4fR8;dHjSO1pc< zLaPfS$elP?F9%xv`Rs9B^?1_GeAdP(Nv!T^P(6q2rll0#}Y1j*U5h+w@_D1c3WbpT&ByF zD(!upiIH89L|2(BwRe@S*n1U3K<8VXI=R2~Cgje|5iA?o)jd34MVguBEL?vx-%_tZ zm)}*|0{^=OuMONXRq0ge2LuEbI#tTP!@z)ijtP5}xoWrCmNnArkk37`t6l9bw40q> z7S|9cn5#5rkk5rVn2$SD9lWvwxdh-y#qcUJw+jz9RekvX*D}x}SM+N%o6+b$(5S-l z86J&qh*{4&senraUytD=}7y)OiZ+e zdb885G#X@BSkZ*i+7N0svKT3mELOum#bmJtBxq!jJsjhpCs%A#ch#LZ<=hf_cP6Ol zrOUv3Jq_67o!c|8Bx}V+sI8wBn+bI?UTFR#d#0#eNw$+apzV9^$9!(?W}95*QmO=k zA-KA`Ja(ogdUSO!09xtl4o@`3*MCAtrAVql!SWR=Gc)xr?3#d$61o&7{c5uUJ1cg~)I0dE8bAh8m+mal$FLcr z(MPb6VXn)A@eSd+e8|XP=&6{07r>!hUHKbiYb=tCLc4~zFH$S4uXN0xdKza!wK7iq zBYJ_2Q;VX05irDfKO_INd2k z>RXxs`U%z{TnK4iDUZ`0Nzql6r}li`qhTbKt190iQtztDHEMD%mGM+c+NryT4(+n` zP0NcZbX)YWLd(YX(9&z(=A|C(8|_Kcy_jBLO;;3oP1hVL1GR`BT6g3~-RR*7g)NQu zu^v*}c%xAuF0jaQGmx9+OXJnePZ_T+;fz-oUeKeCwS?kcYXI{{E_yQmi#%dZnSZvA zg{1$n6!;j8z7^1^KF3G3~P|r3n9Q@B7%s#eBXmU8AnjQ9H>!)Dc1n0>oakLQDBdcBfJ|+vf>DW)qdg#+ab0C@$V^2 z?FdQuJdIl^v+BrZ6&SOUkxnZ2((?BcZ1dkoeI-w<@R4V9N zr%+^oI?r^Upt))>IN479dG0)~ojx?A}*>6&8I?sVk_1k503-@iF z%~LtjP&QYJUY+F9c??HTNh+7eUEGIx9xvcXLwSURAwA+G8BLc_ez2i;S-zg*gJ*d! zM;glVI(uA9^2`)&jNOMW*Ad4G&-E-v8p`!rYy2jr%Qe%#*62df9@q?Rp1Az}KF0*l z?^B7i7PNZ(0;byR)oW3+yL!EJr{W#{a(R9gS9uSs*5b3S=V9YXHA&&BwHVv{v>1xy z=7C{^B0t2*A#c_C1I!C{gO5O3`9H!Okr|47ua7@I6lvt03PpYlKG$<75_tvqL#x(e zLZ?vVC*W~tDDs#a&~K#mLGm4yO{bn~3y*#XLO_G_$O3Vh@WkVxcumyQ?;tN(`P}6J z@BaR6K#OI_@z==LnDnv+nb18>3Eh_qPq}?L<#1D|NBk+%xl6672$E^VxLYWzd(#<= zOJj}sCVnBqHyh~%Hhd$Byy2VmZfleUCLe19B)4~mhflOV8PXZ|klG=gqVdRcp>87* z8Pd@rNriND2^Z4Qg~zkH)a{S?a_Ev+g8(YYaVD8(sXOOrw80}DB$biKV~Nxoi9BC= z)ur;|7v>%Xz>f?R|DY%%JiH9jRVb-sraIqgH4fC9`#4+GZnw0#ICNE+&&(F?4hiXyL}dbS_@wTC0iKtJgr?Z-er3w4{uO9R!7PZ_8#;S5w4(!qgA z)oF!@a|M&dV2JpBVMBboM>xd|@iH6rx#mbYfpEPzoDELTdr14S*^{B}l+EhKr)*Z2 za5k$8$8op`*00u7T#}0&3J#6=+?&l)dQy0#P-t(g~AKXzC0X-Mi6l{+8-ca zX#^)CrKJj{28VY(OAG>44e+IS)mkUjcqF-a<63d0_UGWQV(^_0x z2IYb&6ZkjJU?jtGm%9yTG0r9*>_3JhwE|U2H5eOTOSBeiYqZfM8BCVI%7meHnLUT& zfM<3qN1DrQ_RyvphJk!eL&FH(E}byYgb_``ZhLKWDe@+04(w+Mw#ZP)Jr!E% z+v6eiH;Mu&H0-TcTCtSHj4?1GB`LMCXf!#`!=yb#M4twkhA)exzML8^c6dH+_1N(M zQmJ_qW+BaI`+~@Tgt=Kw_ZY?xnt2l(4VCOIdpTKkI z9)|r%=5XXeRHgMCO@ct6*WDH%LXl9QJOxbcRqggkRHpWRN4iuXCXH!a`H~eez#ff@ z2lfYn@ho6(2L7H8b)C?cm-ln^sa;7nupiJqSodQ-SijjOAO05M=XvZ*0W1Xd&q33q zSmvN^g|*w7%KcsEmWt$G_o41KG(5gCuq_DZOlWe9aG&Qn{Uk@4%c(oW*j}HqHiYw>hK2#>f57mc3+KPfykIxt2;}9x z8d%7L^Y{DsBCG}lYl|=8{r?HGbktDKg4DTn7#pD&VuQFpi$@|)NKJAN_TZDvNaY-Mxk9C zO8?bTgKl9grAt$mScq3Vb9Zks7olq9^tIvlN>AgAYbpW#9(sWV^rDDywp~E4*O~Z5 zr6+heLf2Em_**=rwvS#E#@`Bco5o8RuN$9&@w$YA@w$*U{H7JBJB8TrndeiJ4rUrnl4Zrod>XTb=p(9}C9pK3~yYsm3x7zL)Up|q= zl$b@c&(nCJr!_`p(q5lWFR=D1ioEvf-R1ix4^NiG{;7x5w%Diz#NntidJB-7=1Ys! z%}-gZF5xUz7oOwn^7Saz*m0rPz`F5!Jz00`5opS~vmGKNm6;(I1=K1*H4gbc2q-f{ z&J3tkf@(Ft>B%Gosvn3Km&&ZJ2O?|QG^3w^7Qo_u8lViJJ_P>H z4QvsDf77C9CpInt{#Pr(6PU1123tCtTq0Lb;4s|T#QOc!97jBczMLb?z|fZxt%dei zkdY)Av!8B^*pG%{SJ9-;_b~JhmG8J}i*Cu>J!1y;Bo`-&J*9QYQlraAN$ktdS866;u-#%L^ zx8|!&x(Y|G!qdw9{`&NOI)1?}5ksQ0i!OT9N?=Wl(Wyc3Yn~Pwa3HbK-_i>#HWEc% zY;Ze*R*eGk=|B%yV^4ZG&C{@y9N9v8bZcImAgKm|)N`$cXc~n)8dU;BCXtvN zkr9b0j(lyENKDO+&;ad*x}uMc0zMcdhL3q9_P?+s>trR}eS1b?JG5)wZne50KGQRL%|QfaniIVSTb4jztEA9{w_#x&1-DERwR*w;uy=C|@%ZLGjx+<`yn|>h zrk1092oV{+tcNf`5QQtQFL0max%&)9n#-L#jM%_M85N>0P7A|8Uq4~^&qZH9WL~fv zaRkuU>wtw!^z}U-e?0m!@=l?zXG4uWqc7wYW@bWPqB{}#`eS$;ioPapNuVzr-{Gc= zPUm2&4YyxFreUX3+h2tgX&aCgeNA_PX!ACjXg9$>ff(&M*c^e;PQ;h9mRbjW(#b>s zixQ-rgM5uelGEQAkamryg(=VXN_v3>X`*O&Ani5}ujrx5rPwEUNc#b4lTf!2iv(#} zEGdwtOE{>Y3o|g7?ld_d4eOBLKv-WWNW075{`^68tChM@ zTgQ$R4(R1o-Lklsx50ppIwx&FK^qZ%8z4ogYLw!DRb6l+LJ3;wbBLtMPeFnBybVX? z%coi`aXTV2-H~&^sps6d@yK(mfu5x0LjfC&NFH;0GM`(F7Et&igo6 z@78GhCQU+cBoJQAH&MEwRcbXGhf$P-Qo6?b7)XGZYmH>_3P^fuIQ82Pk> zeC7(v=V(Vh`Nk+CiVE?8G3v02`yzQ1OhmB_10Nqz{3BpIGoq+{%>hIdQLFt&6tR{g z7f}>n3y&yL8;2KBe3i$@RPYBQiZ4UE6uUVF9Z|HT!bKECu~;xP5k-2cyA4e}_XIWv zBZ{Uu(c7?PLy0JUlw*jG*?ov3&4}5(pJ@AzD1M#$B+uPfInrG2++oBH#wnx1h$5$j zVMG*v#qggSQT%u21-lVPAfosVU?DT2_;VkBd_>X6I~7q}gc^H}C?c=mWl=;?bSH`^ zz62i2xSKbh=f`4=8i+bW}{0&#)x;d_DH zG+$b!Zhp!tbqQycx-d5`s5@tzO9q|=*4LATzT6|Ql!az{I!G$RhmQ!TRmL4~R1b_h zoF7oDj60|)OwSjoxWn6fjXUgVG}K{9G-uD&tBn~5SOA<>nKa|2>Y?fCe77Vns}dm# zID!|V8ah}=X%k|(aD<@yK{&v(3R|vZEuzMDwNX7#X&PAmyT-OQ;pnLCV4`qf3j9;d zCBfVwrB9!wNTjbkF;KsTJFekU=Vy@qQ^Ce~q`wIm&qVsnv=E<&m-9CFZEsc&ZWre- zZ^z?$JB!-yR3s%J(ML2(k~42xtet(^B6O-6hJrS%&>ega{&~)|%WYYdqn+?H-XznB zwpZrs+vTay+u>rg1-Jybst)$oR1-ioA*o7|s#0@5Tw5oGmD)D=WNBflws!0pi%(fB z*H(bTfE!_J$EpYM$!;=JbGE)uRV)3E913G7JB6W4_zk6Y3`pi2BqyX!JeGmS-pwWHCNj6mDnAYAg447b~c$n;nMo4}w7XOw1qNHPf2zbRku99}X+&+9xh| zZt#HpAlEMKxs9E8+^w!uo^C)IL#f_mK0US=Clb_%XSaq#ILW9(V6IyB^?#2$9rjhb zm6d0zvz3KLx3haMY)2iZv{ky~Z}%mF&#kyTy7gh>rAnjGIyl*EO&+K~s_X8nDvb`% zZ-ZB=jrttq%C|ea%UgGE9WQO&wRMbc44i`)^W=QHI$J+f#lkbN@M0{iH}OP^$!Q3h zIy8a_)XsEwH!cXl$c`u6Od@$_vfdP5@5nOA{A33%RDmVj-CM7?@~S;IJ?cjI4rJn1 z+w(0ra}^6N5tpvWd~#?Fgt1}hC#Dl+YJ1ZXI5w=>nVzJeFV(X6!bRQnRto8;Ft_@t zI~95NQ=T3rLlx2Oq66NlJJyiw80O^KGj$U-Fs85C!y_4lc-0>tFd$`d^eL9=K<>J--aB)00@+l7ZLig+U^z-$l+tjDvFSp+J_fszn zZqBf+zLI+Ge)H4)d~-R@4C+JThgFke)NFz?j{00isr&u=`}zKIoZ8gq#1FUj zpY>Dw=DaCWeKnuR$#pWqVVKnLHAgldB7J;sQ;38AaJJt_5*E zz%bT=Dh&U*Ye7$9Ua%X{&sxwZ-qHY7yqwWgIbMDUw7e)*1Xj-<-cGHC z;Doijih;zJ;s-~g7cq6%q^_Ab(cL$|tHxI272-o&y!T+G-CVpgUISQMMnR%y85#ZlQJ=DhHC*^J9>n%oP zw^yDYqS0l1QkDSZ@M7@QDoH6OO|yB+eGbEsqI2c(V@@7?!o~MFQfov|qC@BJ+eB-@ zvXvt2p5)Sb40p*(DwoHVI~bkuJRZf7hVr;d8d;J__c@4C(Yb7%%6*$>a}!6J%Vzc% zqQs8=im}+}el%W;nGC~Uc^JcguD^0I^MW%)tioX%qUwv$TX9auQGBK~2U(_z(LMNJ zEj*|mns3ynAx{*h0c(^G@>k+b*`v*(J3;BGVKlnP$2RZB7&WB)n9qY+iuy6+zzA37 z7Gy}eGD5>N&wLS;o#o2ZHseyjsjyU0g8wWl!-mSW7*zpyNZN2*lOtzjR`s(OdxmCAdKH4NXR&-yKwR?G^Q5~? zxEl-YYF-W~&K5AuZf2%r{eEIrEfB7cuhW&3@vq6*dZW5~>yB!7T1;W!$cuR&7L}T_ z5cI}`V!Un(h~O99K_#jX;d(XW4lD-za!^3X42&`0mjJC;Hi{oTh#6SRCUs!f8mmY+ z5!MrToPSGT1JH#q4T#>1ZAqkbUWs4rTSY0K;LMO}i&E?%??MGmx#QIa&eby7Eogmae{nmaB7dkY6eHg={-VR#=l!<_s^8h zR;yCgI`hD7%g>p%)Od~kRIm`Fv1L2cojF@$qGnfP%V5}1%+ud4-^Xzu=s^eK(>?0o zxYVeaQp8$|L^a2G<~C~^)2s}2oK2)*9q1ya+H7@*nq76Qpfy_60{P43{VMJwJ*Y%{ zzKBZvwCDtLW9~4V;C-ANUXvUitZ`t5dBGkBOdw=PPH^-#=-QdiZpFtQ@9Y|JC*8W} zF8EwgXIBO7kX0P%F=!{IPV#gY;c=#?TXs)(-`r@mD~D8yO&izm!S`Bdi-ma^Da$9) zmLDyGbilao@(2mlEh0LD_gF{(&qqFltDipGZ_wvPyfL7)GV%NM$d^_XczAH80-JU#ik$GT$klR_#65@lf7QbgTBA$_|B8pyhTKI{!M_G|o5oXEbu`kA zPbJ;z5-#ah7hc$_lC{#}o~wY4j(iB{ksQ`Iv`SrmGwM?pNCG-(UH;)mhKRKigVUwY+OWX@aBOQ9ohS_=cb)I zd%iL%m-fDnUSREA6!mNGXL&fX?0t)e)VBBNhoFpPh{;5xa4pG>I7M5bZqs;a@4E3R zd)FnLz3am9LVDGjii^DmmW^L5Y}so(;w*027h4{4sf@e!X=uLzwt|D@(!mb!Z)bmf zzSOQ(XiV2L0cX~Zw=FH(d8S21#(kToK}NsQxF1h1u*NNlyvA*gE`VCNa|+rXo-Ffj zc}V*)?=IABnlH^;H$P?Gx`Z=tU3gZQVzrXuz!$)v@f(E=`eu&+QwE(4K9E%Isd#6= z1R(cRpu=QmhjY`4Jd)+LVy^fmj6*8YA)JMB^lj@|tdC%k=C6NisgmixC!p!lt9vJk z*5}nZ=W`r=Ip<|3o@##LL;+~?(+O<`osaT~fF?<~W0M9f_k!o6d?$ceDgSSwFbc_k zy}QmqBPBC3!3dP3)Jh>E`L&11J_eZ7ms5kyzk5E8Jx;n@KMx?4nnz(4(tLiGm%Er0 zAX7`;`7g=!76oIqZd1z|T_1SvD>d zbOKg4n0*Rv9eu2DoZ>QrP63=JQ=fsWM(U8jfMZ{Ia4GAL0I7y9S6l(KVj_wkJBZ~9 zr=h7Oi=z|8V%Z|`)a}%_1U3ejE=*&ho3UMqrHl2h+@;t}+M-rH-DOH?<1q5(RZ;KLD#1YXTT<* z-EV|8{D|#;2DDiEmj8i#jmg3NT9DJABDUw^z+Ni5jwpfq8{wK;EYwkWg!-^STg)DA zn94g>oOE8ka*bCh5&ZG=0*l~95#uMj;n<|hEOA!yv9?3uZA2nby%tFd)$0-t)$78OGBv7Y5NFds55<}aWB21cVnT_^Fzb3E^@dqb27jPb zhAk3gruYN4`QrE_4#iKb8F)N}Sr2l|(AcE|2>Fg1Lmu&GUY#L2Y>)I>)&i;5YjGly>l^h>7dsiO4Y%4IHB2TS8+9g2K%uAMSHbaBL7t$X zCv6^=42r11RCE@P1jYA7?!e@Vt76{yoHO~)cHgF%FeMdD*V z7Wr&w-jHIEJ1Fc$*b$?V0l`S_coesi%xL6bHisoYMxnIqBUj?n+!xC8*w7)yIA86t zTNUWRlyiAYrQK9J$NS`yMx8s1KWdPPSc*~9&B17%y~>g_QZgFpYjSK z5PX?Hr~MSJE*3N{lON-lPe>u`z*0P67)dMip$yv-WLY>DyB<&RChB}X9UO2L$&U-=RnGw$QKKA$s zrxAB5!ucZjT(1#MWEG}vig1dKPr2I zb;y_Ibb!Ih?KBosHXSI2!abNchk-~Ho2JCNX-GQivVqBfvAyYOsBtnSERW~~7M6=5 z#$k3tlPmFbmF7M*L8_nHOvsD=0}o$lBQg~EbPuWRa2E|lJ`3tLB9P!*iy#HgbqNQ~ zb>V298nqbWTr%iJSfB83WH(89!}gG>JJo2k&m%A-l|jiFB0aJ}$q#tgGy0Gw`5tfy*T zw^0viKjv0~x=rJyx#`BI%uSbY=B5jS1C#hhPv&-%M0Z z2237Jqyr01&IB}FdMy2#lm$ARe0Oe}~NTtG2hJ_TK z-{EC|Qo#+a9q_K)O?x+9UaL;;M|T`UJaG9L9N7+6$j!7MVFYhdt5pub8Sdw_50>Vu zZOSZZ;Z1b71qRM$N7A~TSyG?brGpF`6oHt9 zQqQ%e6Pi3Out^wZHBE|+h1Zf{R@!q(f=>lltvnzTCA1#$iKJUO-uO7-860UwobWWF zwWF(gbTQ0%T;of*@A0f%%#r4@=8gci$E^$uLztX4h7rP?WcbewVcyETU^im;*_s=G zgUk@-<9+P$AxtCgR0#8z(A9elVIr$Axl;&JbSesA{z{G>AtB5yk4`3O(&(&1VUVV& zB1$2odVGjt;0+AzIUa#&-(+l9BOQt4kC2-q73F+&K%1qb`U>Q0Opb`ZgDIHr^EA}} zU5WDFMK7=@UlcKZw;Sh7=2`}&V1B{FCz_#*dw$kKYWwj;dT76NzOJ-Cht#>)Sz*?^;@>;JaBzlU6Bg;-Vc}Q(L zjlKmcC=e1o4eBkhCsK|eH+Os-a@z2 z?d$*;iyx1)CCF2#g%8J}saKV(;u--Qk z%ZSxgYto3+Pi-(1&KiAazB?!bDC*|56M}*h0#OH2IjTv>AyIq5kcD@uI*lVrY>4qB#oxMBFflm$fDoJ)l70UXD{f8uv(! zG$R^!713IO!sD_UVB&^rEfS?(=b0hi-H8&n{pgGeY`GAAfv=)W|#OmP8MN8Z#oK&W)3bPv`0%HIp? z>jI#1^rujVh)Vgd?fEKGgJVi7=@N$N#ppihn2u+EKfG!}@&0RjqIUyd(O<(`(R=VO zR7><;}T*#VJHrmz2p(C2Cg_)@lb;a zv=DhsEUiRWO6X}}s0!w;ZoAd6f>(8OO?ZEm=m9lavJ04mMIGQZ@UVlN!}OJ>mUri| zqS3y9$R*Aa)}M5$joFErsTMBHSK!FX7A)O&A%fdXQ!d5GDP&Hg|RELu?@vsTX z8xU2@Oi15hWBl-bSu?$I0Cj;9j|N?W^S35m4L2A<*t6cTZup8}7x|@)@uLPRS#6dBu2;(@s0**dHlB0sGI+~aWzTsF+Z)iGlh9rmoLEH%e7hpl8aD`SzQwlO0)-!?aU&@zWaJXO-<) zPqfC#04H*reU_UFh2v^B|4?@0v+{3NQTZ?FLmp4 z)iIhD#ZXUUw5^6gRHc;|wXqSS(LDSUHW@~j;u~THn==w{ru*k#Bc>KTqa23$q*I!z zR-3ZraQa-gT4_U`+QBBZ5d8z_vBEci^t2JNp#UlXMpYcLG*0Dkk~F4z?7hDZU8U6QNW0_NtfS^VC_2G)|96gTWZhEy`bqp%2HDtedvt zRj?fl-H=5*o3Im~hxR`?jhT)Grj@g~IFLPbiyE^hm&Xl$a#5f3O)(GR`0Q(E1#!=ZC@?L{pDxP4q!*7>eI?mFNxdte>fe)0Ucm zhABOohTbeS6*3Jy_$nGJE8xOn)^KV%!o1*&X{VQ0wZfvWBa@@i*WjPPY35D%hL~pl z&a}{(W^TEO278zi#8rBw4s0ZaO?{2S;|PP=)w$LIm}7Ciz?lfA0-9KH(rL6RGl;Hm zcA0L?A1+nlE)1AXVD{D1#n9?Ea`~Q+%XbRP1&4hj7h}s@4vHN1m7&0}&vb&kVgEP4 z9yjbCb#czHFBIr>v>fJChzXd}adfv;S##1lWa4FT)~|}Ih>Hu4WqG5elYTEQJQwfK z#l^Ns5o*dlQ$u19z&K}clTo6c#7tCVndgK=RkYlbKHQgI{g8n(zEImL4Z3H8RP#Ep z3Ls-z_7DmowAM-#bOeX$a)`#szD zT8=Azz2a()G-IXZ@<3V)>vN4AMp%D8!&7eFbB%eyj@y`EYw@eW0>kQx&^C zSciiEIq_j<&Gl9VZBXt6dJ z<7$=Zn}15A1KX&4>?QueM0TsAfwWk+I&Ke*l-5$0vO%WAsDUX29h{Dzr>L*cLH>e; z)WN9%&67I7<_%Z}1@kyB4PaL4;t~`_p&@Ry3M`Ten6U#!8bhO%L1V&=9>(mB9(^AS zG(2zI`ev%TU+4KOb|9(eM+cBfJ)`If>DfhKwuglb$n;G$7Zyt2RKADSWC|#fG?^GA z3Ykyed=4}(9fhNzkwtr9dZc2@A@xv}xdBDd4Y-c)DGI{A!- zq4@G_peSC=&D~VBQ_7~T>wBTeZmO;zO{+Rb;JKPcDduR}f&a6ON@xGAlT(d_>O91& zx(S`9X_usFwf5b}LT1%)Lua6Qyx%pChxcI~XK>lQ#G+}?V!Va1lO&Ow?Q2+!bKLwy z9l4g1pp{v_?okWduR^_*E>mj5$RcE9$m{Is>cx3HybiWv!P1_Z?hC%9^&0&n>R~kc zhF@)BCKwy0EPxRubifogfOy;{fR4A+aAl8{GA;37czMrt*OVZ#+NrmiD4WBrh0?(~ zB%&;I79bx5*YLppVcl*Pvs0!j)B8u{jy1Tc^+3I~&{1!1?UdRJ4G8B_(3(Unpj*I}bhR!gdtiz0g6Z^tlg>idXNZk!>aX;|u02N76B+;`J~LEupu7hY_PXOJPE@ ziQv`66r1WzX{s@O)nVE`D%yT>K-&it#ju#&g9U-6eH#jtE6TM@O1?M(OlbmGo|Fve6EJH zlAI$C?8FIMOp*)D892@Nb~&WoJ}#1ealVIq)!UPU)9oceFUZdw9}$ODfrFvHao}92 zTzVBaA!pVhzj>}nKOZl`vdI>Wi@gWZyISaQC3J7!{kxCY5ArCw`}U;P=7B^=!Tx_wx4O+kK#icCV7{ zwi=@!WpJqMM%pnbTiVUJrV`S_okjV{A3od}=vd&+aeoZHukU(azlzyH)ktd2LGAd6jt*d6JkX7EHXV+y^S=LS!biDcbaRnX5 zVdbmc=}wB#s!ds)wm;VUj>|vyXg86<^>!c^ah`ZCJFJovU|za(k~Tv!a$WwJYC$pH zoTo80#^e*}`IYSaufiljJ2Z_Lq7S1)XvN;-oSm522$4IGS?+T5g+Pulhk)hCx{!Z$h6j5LIQAX;m~=Q8L+NjA+hxTX)w zUDp1S`yS8QFFDds)>g@&K$1Q8ISk5*&Smq2hcP&ZXY)9YG?dK;rN^Bl$C)G>W3I?; z$99f6z8zy6X=pn}40cWOpDNlI+mBp+ujH8E`Q5{j=JK08ajFz3OrYU<`Y;k`sto_R z2{cp83-Y0^Gj2#K?)iy*vh=+PJz{q_PsYHQRq|~!BF6d=*xd_AY|ct& zyj|_04gZq6$M)q=sZ13-Go%i~8_n6TWK>yf2kuLm8XTj|-hul@c-7dn$`s|+Y7bW0 z&BZ%`^t5<75F;bI4FSkrNNRPN6`;=UJ|qOgGMQA#f$k45i=R?1B4=i;Aaz&-EP zxE5mVlNiawID2xpMxs-3Hcn7LTn zRGX~{QFB2}+{}HV2Th2N_o#_Adiaw{Fm`&>wrxuK_@^uO7RUS&SPXPBlF$eI85qER zA$il$G!&E$lm6{~~&-0sn>Njg|oV-3fTU z85oMJV2p*K8mKY>Uy7_-oa*pa-d1VvgBw=2ZQBnBcVDOXRfyFOXI#Uyf2z)XTn^-D zng9c)hmE*MU<9p(xb|>jSo>-1!8AVFh;m4*Jsj<*NI4^kr+SE>D9TxZUq=MSe%&CU zV-hAI9VD}FaRm{i{HCSaZGyjC?k;Ay%l0ZSB*H<-w@+ZG(v4vuBNkA&sMvd{3xvPJ!F1pDLI5)tLvlpVoNjA@^w@4J3g zvAFd|nHn6k%#K@s30^f;8ydHM7rZ6n)~Heux6W%YdS5bHeT3#{GAyCl>@mmkb^kB4 zL&m7zjeqtRqrQ?ZaD$!83-gm5%s&Z_Q=^-wqtm;B{kVzb7ZZ-1Y7}@$-6P;7G3@vv z(pNdYN~(ggF9l}zRh34knvOvqo0g2|q3Hs5B3!a3$PcCSe|{}(=D%3H#`iiqOkC3a zFpi1Ih%jE0dB$c*oXE+E4B1%$ucYHwny&Gs-w&2HFs z1@%Mq0r|`Q$Tatn9s;-G^V#FO?Scz)^3$UKX?k6caaC z`PY}jLC1LPW~B*frZDq2;owNfAK!&D`mWobn(Y&sRMp!@#Gy}O^BHU}Ye0?d(mbTD zLNrqDDAN&83|8WZa-=-LxD7hnw>)N; zqoBrLGB#(s*sJCbZ$}j^R_)$|?%_+}P;_X;dzlJsQWuFid-gvGuUa1Va{7)hG30IV zQqsXLnivxOI~uMy;ZA7b|6}jX1LQi2`*9z#EU)iNKGw%rzIJVCW%W_M?`^R&COo|%;_g8^gCFnqa0z&QwKfG>n_AK?dtD-e!wgfjuY5HJA(;SPrr z_*GR`U+>j>-EVegfh7LJ+Ig?LUsZK=b=9Z(fZlxC?}>Jq3E}sKBBQJMbA%HwII{gK z=&KUgxHcyMKby(L|70FE{sUABI*86c9QDWeJcEss$3M(U5Q~lLP#lOecw!uJ4;kV- zZ2Y$(Z7w!$n;%NP3>$+w`igNnGJ!1SsxiGKI=i11}VHr#)n<-{{JUDmW8%hNm6s z;~*>C@NT8GvO-5%tA}kk`?}g3pQ`Ud2L$%1*We(v>DqW3e2DSJ%uKxvw>dPyKbeAk zCCy5^xmQgX&Nu*zf|H^jrzuLg@;IVHFuZ(s~M16`cyX=ri`d#MUXKuuIDyK%3+ zAqAVM&p_Ado$8(crrcSjx>PCE!=jZcxfpAx9p-wVbv@!+oz>UY+v`-{Z>u)Ppoem{ zJ}HHTRgh=6I1{UJrjZn)qzR4L;&fuBu_5@%7C1Av`!wMl0r7J1r_+SDpomqPu;54! z=Dlc-5*NvEl-ZQz-G;=qw8;|R84V(zwI0VGr2#E-$rPy)%=c4v8Rn4!u?hnd-uP7P zj-&$9fg%+ak~$D%fL*R+U?C^}xrImk=YZ?z`aXrvmMD~gkY`Fob8wxfMwUgqKw`Wf z`KrGXXe!KC{a>Mi7q%<_FBlYeVJJPfn=keN1%7aZPBi5L29sBZ$djP}EA9*w@F-|8 z2MRbUYvcBMdoGYv^uO)}=U0s)3jeplW98lp;eRSSwZOZ{zC`lyW95ju$-apcs`0F^ z@A8MpgVgRqGECnPTJRJpKg0AxsOrSO936xL;LkxV6#!$m$sf8#5{s}}Q+U@PHpsmQd-WIZUcN31*8AXpZoorJ!Y2@0BS7h>RtFyKtTYSWR zA>|5b@*(@PJwLg|WOU(uOjOI@O0-jd{4urge3_nN5`qxEv~j;yyC^L;lIC zfbwYY9X*3#)HmgPEtY_+-!WiWPP-nNSJwN;yuzKJMs_KD@oGsHvJdh|sc4Q5a(QG~ z^g*nMlgm)rs3raIK_?Vo2OP{Erz`t5^sPAVD@`H70hh6tCv6Wb9P@8oo7v8;EJ z(ELaFiF=VCc2HCw(=2rsJdSoycn-p-+<^%6^s+qXwHf)z^YLS_{}V}xIww6j6Kg0G z`q`G!?4jo2W0wcuP;FRu4cQR0hR=Ouh$Qp$$_NS{+?SYn8Im=u2?f4_XPRGPEkR`n zZnvc4%r{qYp}4vs49^hsAP}DJNzkd|&0Vv?Zk+qbXX{-7w(LQ_eAM~dr~)AW`&EWg zR!hC|+)WT2*nR(~^ZkKAtswNbPtiXFC_;aq4>kXIps1TSDSN2-r=e}jJO>zt`OKl_ z=8bfyxp{d;RG%7obmGdx_`xrz36a$<2+;Fk%x?~e5T(tBF{4^X9>)BVh*tS9W<7?@ zfWdjj^K+j?=q2KlfE}Wt0mml|=hE1~JSn}@zOcFBp*2?`Iu zp+4qq4|063*D134DQ61xtS~H>u{x{e5Mp=Jme<;SUp7!EOhl$98m^RMW;qL z)4RPF*9SB)1*%>H#o4dFsYij2=Bd|k>g{oy5u9q-N^V0AQ@bh-c0{iYjQ7k8aPmZU zM1C0qCGpEPl@)vyVq0(h`R6I*)KW96EYTUO;Zls_iN?aW{uL!Xy^0MxB zRJ=kUFQ5ItNVBiEP-ys#H(2-z@Fw9KIU-OWC?kS!S&R-Pz3NAF_!)uK!szfHgbHq- zTja3(j*2*hx(*cNBGexbktfH1R@|8wa2>Q*HU`xDCy-Pf04l>o0pL~eI5q%0FSUOH zrm4y4`N_!<_+t!bw2`fF*z|Nwo8jnP6#q$*@`8!Zu--)x_Z5GQ*MaMSD+NMfvcHhZ zRA6%uR89L+?sBhXu-r>+;LKa^b%4->O0Kl$jQ0qVR z6x&r@V~LXyq;4=-8R%KdPv1mph0`_KeJLKS177AR#6Fnd&xgGAK(?DoV0q4TqglP1 zR!k{R6~S&@kPZ@Znojwsns~svM|Fv824boNXUn{pB$oFc5iGyWZau;p~bT9O+r&1LEJAx zf*9gfT}+eE_3${_!&ygnu{h{9E^kjyDrO59faByUFo2a~rV`EjuL2CShb z%Qso>`VNbKG=f5g#XpQ>4JS+}@D+r`FNA3WSNK$h@OB#l#n;hAH|7u(7YCfEwX5}M z1?8t8@ko>O)c`XV4`wj@%Tz%G!__O#f0e-SCCHhcFw_sD1vE?iBtR4T7Yv90Fi>REJ%^=A@;a?{xe6BG!kDGWD8V<3H9S%2dxlwPvfwAL^j+JUv z$o$L<+z+rdDeU=VT8kmE0ms!*M-=9&V*U9a>XbY8rq`-z^3adA31aVAbu4+$x5MLH?|CXuVQ~6n zE2J9$D`fP=w?cW@xwpcnB`fq!e4b;4cu049{mbg{=~{KRrxpks%(Xy8w_?Ja4)bfo zekc!sAqF`AwMXA^qMXs8sVC?M9pA7irUk>Mh}VXVe))#&Q>ZlsL5sE=h--YDRSD3a z-WxVW=|T*fB`^6ZQra)W_V0qo3Ju%82^D^qhK)p>YuLUMqE5h3Y&0u5yyyMnf*D} zNj=Ojp*1x9*yta*tv3dg&$aH?vC4sUUmVeN>AzY!lRJ>)ewq25g6s;-{FG2(am_sL zw6y-KKMr#3eJw<`Z0~J1WbFNw(BcB@{Zo)2c4So#lf7RLk0b5<#g4s)8<*kwWWZ4z zqmL&>>Li>+a9Pe6tPg8Pj{lA2WmTkT5gp93!AGEjtTfgsh*4C^3C0qXiXf@K- zU$%L=3g>L0IY*FMEhSNRJXb4{@jn+=*3fFF)p|%Rs0}j$ljXn+Sp8#=r#P$se&kbG z{Ufn*yvMI41XkaSi#V%)E__I``m6DIp4C@`g4OrG;VQf{CFwP3K%7}Z>sQQ!j4n0A zc?StyA=1{91>F~@-3Yjz2J`~%)tzhLoCNm-^ARlBNe7m8pP79+l5Hq83E36iom+Y_ z2}vIeO+RO6D-EfA6)l{OS3(wQygp}6Qne@Di-%V55x8WehFx*rD6 zW+;n80cNKD%E=y*aa2|;+BitBeBQ<*c|#1%@|KJto77)+ZaiA(3nIk5BJMGI;4&5~=+v_@jiMC!GEte}3AK!2eZ@&=)T%S7M3kfa6_xlL(yF)oegw z9o!LD?U#4DtZjxv@--xNF!>5H66ayuh&7al@ny?rcBRo!k9XkyD1t;@YV-r7YdB#_ zfiY>R(L=CXS0_I>86qywpfxH?I_3a(BHY}KsO>WXafa%zL_eB zimYA*6?v)RQ8^3X74T1=uGs)xjymrQ6m``(xd;kN=M$;B06zqsM#W);DF}RTG6%)2 z2w0ts2r}wy-bm_fUalS@`1X2d|9_ss}mx%0k` z0x8vbW&##09N0tQ_>5l$$XS48QlHD1rk@4Ah@+7^_Qw%LxnogQr8>6Q9Pkob?Xa3& zfa%xs@NUB^b7_^WzU@<;yFzD6q(+ZT`B!nNtqF+FU4f9#>J=*ol<&|&co61H7;T&) zQhq#mh~A_M0Fiou5i7tZ^KeM7Y606D9Uo|@0x2?D4X6ebtkVbP;vxO8I2RI8>I`0W zKEGNmjH_&Uufl+{vKJj3AafcM643 z%8-_aKAsdH$F(KNawr@R%H}{Hj}Ls&8LfLFigL%ItV(sP9~inG91_6Lhn`~f{VK(k zI1JU^jp@2fx`G5LgrO*3IShR}zR9c#>dDHRRdhEm*nm+$Tp~ixQ-#peZDIi-=b+n; z4mDTOj%R&PdT#yP@VRb-UL+Of5DI$LAfs^Y!|*sZ=pDX_*SF9edv+a* zJ(F4cY&sEDqJ~lX>Z;TM|#KO5v{U!tjDbO zj=iK{=i8JK#A_-mbPl~2YO2F=__j>gHUKwan~O53pt+05oSmbN&7mCwSRR~JCYE3of;e_$2DsNk!Y)nr#cB{iO zYts|0wQIEje(-+;yEe1e`5(eC%#WXm7!rK^>KGJ-b)HM1mL45&kk3J#L#N?ltY&q3 zbZojYzH{#j_Uc8Hoi~9Z&%%u=Ybz^SwI*B>zY6w2PS$s<7=Rb>vsG`*!n-vi=h2fU zTp$a3_VCGyftEU&3VzVl_4)u;$eF9AK+Wf-8+&G81sYTazaC0%UbpSK%1zf)uHCS$ zvSt0|n=0FGs$6yBO`FzZiAgB1i$3KH5O}t_G1p$L+FWhczWf1F?)w4%66jZU&6BTV zr$SCy^(`i*ZQmxL6|tSIrh_*@H=7f}(0ny`sRArHn1&SzcsLl|tc(U~4mzWLcLg;A zj{c%Y&S{EdbUbsL{2ZxM!D3&&Xhf&JG?@G%AU!iv8Oa?5lKW{yEnbrOBjkv%Ko&i& zJ8>5qcg}T($SrEDI09Z-sqGk{p#y_Q5ZNIcjmS#1WJN(O3?_#`LvdLltwcwICG zMT_EW5QVV~Ta=LyL?MacbSsAFR;&o9_F!^m1T(&kJO)H?T12gA5u9$!;Z|iAHPDTV zh{zM*b4LAvv(~a7)q-W6Y7QosM=;^Dek`zlNkpw^)*r5nyL*x$EJLQ0C>j}cr914l zch+TVf6J^&_NDSDE0u*dZUsh-4klY8Soa0C90Yb#M6GCnZKJvFTFM*q^`2yo@!-5l zW4=8?rlZlU@2JnNR(G_oLR-9&k|lIgJ17+f;p!rH@DN*5f{B^3V(iZ+t#Ij6gGmx0 zCSSP6fp8}yYDEioqvt&6rL?Y#zFM0m4P#W$k;gmhxs=ZAgH;ox`a~<$9)HVy!ix9ztRj?2t=aabSnHhRw}X>2rz(b>M^_tX*!vfWS{0nmR&1=nT3kjk#tc zfm5kkx?y&z3d>lvc^hyJ3h99Dvd5#9k73Zr0}T z5P@>m#tJ->wfPG4c}~{m7)cTLCb*GI?@Pu3iT2@MmJWc%R$~Rc)Ry_D-hDp_aOn3A;z#$>i{dehdNo!^zjMpVSs> zB}MCEX#c@+5%hgYPOU58Q>vqjR~@n6r1ipROU7@?J6+{&KBoHZM7j4X?5 zHY5S`WB&h=KvUuT|9PQ;XQ~%)A5!f6|4N`CcmDruh(LM%w*t@1|IdULyPyA&SUvwM zU8ecJ1CMj(|J1o8r(M;Ug`AB#0l=s}B1=^UBem-rQPQY-a==YM!eFvL{8MCTa57{p z;#o+vnhf{B%F2JquB_nE|h|7@`W|Dhu_>^YPf3 zJk34nkI!fIzj&2x&T$E5WLRf;en#At5$ZM#Z}O@6#%cZFapS|voLR@br$C3 zS?elM{c0rAiLC)63BQ74!suVdcXKVJ8CQ_z2#67j@|p|O@5nV5M^e%7DkpOk0;{X} zZG=E-@%RWLc@XY_qDBZ&>zmHl2HDA(28=j33I!6&6*FYun8&+e9JDG*CHD%vE`nI@$k(7iN?FtLdjB5B|`dSfyV6g9!g8fg9%R! z+M`bu=yX%n46Ee(z%UG&??s5n_aBx)EzMU*VjLE0cL~H`0s>!tq#8mx0X0TWCoI`q z5EUy2Vj)rSxfmj~!Fh-Zh)cRZ zvdX>|E%_}Ur=pZIA?h;CxOR5z1Ea$&9 z9r(+qd{|^z3_K+U`w@7K3N#f4o{teKxbBn%0n1+?78`h;3pC^g zp0|exlmkyI@J!%&B(&Il;EBY-Oh&-7(p3sPkA}w_xMhLoRN#4r2|QtdRa&q;zE*+t ze&cj*O*;0BD{K@#=^!ECIw6^Hd*2JT33P2UNG4CWGUW`ZPSnDXo5ow#AE2T=3pw|HRMoQ;!2~vot zP`+|RbuX}&muKWirQ00iMH8_4xLs4Hnzb79&GERn$~)4`cnR6YawDwH9r=5+O?z{D z)%{ftC`OzbD6qJ_lfTRg3y7~4uc z*pJxu#{&I@vF*PL6y^KDI?-VFIMsRt-jq zvBgULzoPh3o!bdY3~Qau4H zFIGzRya*E6!CQrN4Qon)F)5`Q+OP)Z7Gg{vxxUmfZT1R>brqc1^iqD>ZKBG-7Pba# zLBuU4%Bm**9S%-wy6*~%=M4b?*yxT!+iR(U7}}~=;m{Tw1Wg(Fz(#RsGTI)X2t7Uy zZSM>eb^YP8q3sy7ZJFoL)-az5ZOt1gv^6i!i0V}%k4{{97;5+h<#n)vX53iUkUC!b z)d3M=QQl0kj*5Dl1SNIWj#+)eDl?`vNrmAdXs_~BB<*$PO}%P>^%+*Y8o7|3JP@GV zb{=c)3#o#rx$4zIHTMkxiX6>-U7)C|xyd{fj*sM$H$rjCJZr9DKBKwjjikBe<*{-X znl9<&6ad}CHoDTy=Ldw8(an7S2aECr3=fZJmE%-2`H^wzIaIV~kk8K|h~#}1m!Nt-o>Zf6l zY{%&lB(iubD2Ci=zjNkhckfN5K8ac9X05UtwwhOAqj_U&x;8UFrp}-B&xon0r^&d& zhR5V#Nc3QGQ3RWulV%4DbJA-fYH|OeaH9Ip2oOJjV?}v*#RHac9qkaBUdZJB?^|d6 z)yhnDk2+Fh2JQo_!$LOpY+Jb1A8#N~vrok=5iqBrsF`MDU;|#6U8$?H0;a3D{%zJA z6o5XlX#@J2&V?{b34RYKv08Ae(t?{K`qS3}JcU6^J-yCi`qp(@Hf`8+?OHg`1w=## z#IQuyZMvOhy^_{msLLBFv$YzeUtrp=&9>%YXwbnj5O3^h!PT_`W_kyK&z{|`%vD=> zQUesPw~bgA_oG&VH6_9E(h@w>lVGu$GZLwzHc)c|toRkl5fG5bc^FSQNF)%RheTRO zvFjZV=fV*vqqSYl>H^kw=q7TJM@CEwHY6OX+ZcjB`T_vHAfNymUZGtGs56um>D}rM z&0uzQhkc`Rm&?opqs27iy*!cw+IC<#NM442rXark;S*|NvgKSi^TA;G9mYJJ#|6QLFgqml1?q z=+Y!CVg|wTP8T)JP)H8g1|os&2k=kGX;zbTU#tpAYab+Kv5>dpBN%2E{8*$5Ry<;7 zo*T9P<7DWa%Fsl8TrB~CU$xnZ+U)oqI(SY39sZ!_31Ocg}1LA?rs4Z%wd zt_;xRzzvTG6m{W-vOw9@(6(it;ReHg25vBKB)Gx6JUrcHX25hZuVD0GJ=v}lto=AE zAQY4z$2q8hQE|>-augNq84z%91d%*U?t!A^hRKQfc1}m0MMZ3%6qSPR`9DY*&9lnv zN5Kfsir}2P2RZL?_mo^H^7;s3xtm^#!YF0U$}bdoe}Ei!yeGFp;dpp4=i-6)1ipxa ziRQ1tt^qN_DIsFu5)h5}-E|K&!4g7FW_s@7a|wU6(=FNsvN#hVqrevtQtw zoDJz5_H?^YWF;8T(b?$O?3A3P8r(*1aMpQL@0Nv_Z-rKa9AiEJLU#_ z15j3}Q~#u47kV6InAaxSd15Rw#e646GJ!FlWgm(Lj=k(pA~o}=34?Sb|3R0v0&9H=2JRL zQOtqx7>A=6^Z6M3IZnuj2N13b`$J`_n9-O#327Qko`4ibE%Hy6Vhyz*;&FzdV!w$e zD$PGkRAwamGaPyN!bJ5#_>eqNJ%Dd=CMqTsro*mr#7p1;VYQ^O-55oHoqj}tis#4^ zm(*VVBz9-dCNcTDp$TnJ<{vZWeVN_f2;Etvhwkk5de%NTRAo`bWM{f#MXBgnFXycp zb2J0KFOpH50WG7+dy(hV47db)Lw(%Bp3XyydpZx{G90SrQ}ua?DtQ+Cj8rsd7W`yn zS)2tWX8SP<{#>A`a2EWDP+_rW!S@3VxwGI8Lj=mRpcQy#7W_+SvHMvNiPf{9(p#DZ zUki_OXTj9|w%d3b)LYpwnF_bZ!zSr!8xF|FHE7k!)tj!VY=I$AX^i0so|V>oyT2znK{(ZmI{XwI)V=tHuBM9VVA@>KN>+S z3;n|=kWzN5JjVIe06FgXOt^qN_DIs%%z7hW1Mm zH1(Bjkj2y{Wn^N0W)1?b$@$rFn)4?bwN_=e0qb#^jfr{K@NS#~TD~)0ovn=3%%v)D zfBfvEGx4t+fCW^I`MLRat1<>R>gcKNWI zpy!JJ-b@;ElpJ&`47kDMK=`Me_k-*4w627-kO2nmT7qhsK*`rh8g2r>fTK_b7)}Gi za{&hBs4WCwI1lbDtJb!h4}AJytVH3N#A$!jAS zLiE5glw5a}bQ+dG zS@Uth#Z&Z^nIW)e4LoM}BDl^pxD>);=L<%8>;uzbH1QpB zTXAn$XoHcSWmG{#deo~R(sN2NzgiDN#e6joNiPSoz&YMqH%+cLW%-eaY&73sn%+U%d*d zf8e;UMt~wmk*5PiT}4hVhQjf%NOBhxx6HF58|E{LY~DzUY+kM@-@&H4I$cx-mB(*) zrSe+?!p*3BzJrEEc}MDRBW4~3i*V)%h3R|<*}qZIoYhCKxl_M^0x8w0 z#-<6@4{W7ys^PB!t^qN_A|pnP5m)d&8y|GLY{3 z*|*0zu{z!c#1xR!yXNc78s1V48(>?o|6y{nJ`Ou$2}uR0l)?Zmj7x9SB)U>zvI7X~ zA{0zJGn&$H!|e+|Wq~El$R57`;??9A@Npr3#nf`ZKm3+5^?fOntUKGe4sy zbG$sbRt4;r-B^R${x{&n7@p+J+hOPoCa1$cQE4r#NbfAcG0Bo zfgi~O`@_6`F(|DJ&Rzk8=Yq4wXY6|Q*9ALjZTCRCR@B0;GsT5p>85faT3%jVu&eas zbX)ph6FirvF97P+fP!fJ2X~p?ggT`F)Z2OmHm4cRV5moAODGsM`@(2HdDLT(oFS5G zIZLX@WC}_3&N3ob-Y&<=zOz_l_Fdtja(7D<%V=a0#&PA3**iI5eKVZ8T3p5q3 z(R!g!VX-*a(g(Ipz$`!BZZ!8Gh_?qOSX>B1t9|PBG?WFlVg_~cVI+Mp`5-bD1?zSCX{AV- ze`}@Lf3WaN5sb6r{CT8nm~C0q?$t-}nHY2c+z_0W##eFCZ^l31AIN9o5%l1Dsq*B4 zL9P$Zr=OlDTx1fiGY8kI-HU_beh}c;y4DPee3vSSpon@UgawIrNtam@g3$sV8fWy6 zCYAl}2rD0>d%q13?*WSTnDf={B-z_XWsvO;vIn6pqJl{m*7>*1dr*J6Om)5kcgWzY+;xEJRQCrOtZS{+8*|Os0bbD#XSpXE`>02foSK8O1SXw_AAEV6VJvKUO8yzy%ZY`Ji{~uP(ebW*myLz(I~xnrGoRw0NEFMl@V`q%b7JA| zMV7@_SQ11(V&S76o%JaTW8uSv3a-ssj3q2z13~7-!iR(ilw)Bl@U-8TdR4FmG(~TJ2ajW8;o(dy>;ysD$0CnPkH``=jOr(k0Lg*sT@etVnHGmT{j)nHqqRs7 z_-3%)r2i4_mI$`lO}Yu`8fFU>72$4hCJuW_^ffwMr3?ak#JDM2yUMCcWk_Qiuvi^R zP!FfpxnxaWp?TX8;M6)w9NCUj1u?Q!uLP&BRAl@307a;B9NF#(6m{LjvXSi*pl!=M zN4AFfOk```NRh31d0|(*Y({0LyZSJWkpefeDfTlt>9;)~UhD~Wba50!I=VMf(Vj)J z?}#9hhw59QXt|*}Xd_u3fpCVqy5h>A%B3*A*6n9{MN}S2p(ia0K(*L&$uOd#GgW z`Rxc|xu?E~!YE}_y`T~^BZ3(!jy)d=kmnkc|pYOLou_p>th&}PK9DA;LOy6S9)ibc`3lOQ%`s`#QDj$2A7_K%zfb`{P&hQmLugk9H^HpUfvxCNVcj!5xxz%u_fz?cmY zIX-@fDv0s1dL=lfetf)4v!Dz#Y;`mbjIzTW%mP|l#%RFnTVLqd!=8dGK=H*$DJ!|@?6I%l&68uVO zoxUa@!i-KAj}+dd@so&=!eJ+x_sFpGYidw^!`W{PIt=doQ1Wf(S?54CuN%b0{5E1G z)qhO{>pTa&3Pl^5gS<@|7u;CKtB_zpI28d*D&%09k6SbP*?GZxco<zSullQI8y~p z$B|NgKS1IFOj`QG8SD0)z_*>L@WF_p-0djIQr%u`VHj7^-fAgaNe2g}W3#x@FiOB^tK1X;+!Oj7LRuPjKw4^U+)uqs9MIo0)3~=wj zMNqb1Xq6)&yH0|=wbrP5n?kGTp>Hy-i{u8;D$7lBEi$$!Xw_pS0%hFi4ykAk?sE&3 z?HgLPOCm+4x+xVcq&nZmY28D#O6skCpjCe?&|ipFy+Ek2*l5-DKtnEC_1qAFGFoK? zoK{v$-6k06nKwa+45!a?QU(q#q zj%)ngK>s=s^|z^L5G6XjF*(@+=x5cc%BK05v04-3N(UBd?X0UiCR0m$ma2N%KIor@ zZwfdb9_UBg53G)BsRF2@ByIEZgnUZP_d5lJz(`?RUG>1j0xXs9f%B*9GjK@fP<>Y2 zk+-pWH|@)wmAa!@YtJ`lC3NlpYDV`5|1#pB?wAVDp6QMW-5vW?hEiEV^(tr`%+UkT zr@}b{_Xa3JX|heYCs5S23CW32xC9>eL?~{VXPaP{&)5X>M$%IA^7NRFG#%85Dh`^9 z?RTZQ)qnsqnw#%OVo^rpz8PVWI9SK2G%{HKlrmnuLgPLd!8*_Pe~aP`&G#M}cg~HB z#wn{wAbJzF6XAjVcmPAY(T3w6=s*TNI?GhC8d9bfD9YyqMTvslJ`*7=?oyOikGr%a z?DmrgV!3O7hyp3qwWqh|@!EQr5vz0vpT%6UW8viG4YMj!BG^GNcv00&|B{J5aC@M~&hdMJrda{d#MxH{ zG;aXH^EPQ&SGel~OwOOJ?RF0^iNZC{5ZBA4TFQquZ|&7Gv&RD4a>q7qD|Ipoki9La_6(sJrT*ls?PM;+==5M5G65=D8VSWQFgFWD8MG z%T_Xn9HvmulL>Xs>lC7A$blK{3XtgadQX>#m9fP8rJ^}l;uEQ?L)ucsgc6~p&U?HZ zK{M39RJ8CH(uZXl|5Pd(O`}>FpP|ux3^ejjzti6#eORXPEmF}~8keDja73o5Ouc}$ zHm0Oc>8GU6%andxDq2XXZ{l4XLJwv{k0q_|2YUQNf&N1D`1?Wymx;yL2G{}`a?#`O zh6t3=V=M3sdVCwS*gblT#DWh;=&>?jgdRT{9;3Ae2P(MMab(>Dc*7O2wKUt9Q&5_X z8F+kaZF-`qpJD!5>HYFf*=lAGBqvqL4LTA2iA0+3Kz0<;d>mF@tj&8P5hQYWaxT&} zoG_)p*zYycydl7tjUyP^TTc~4q*=WZVyG^W=EnwT!;pnhrAG&fy75+7q7{vjeiuDz z`m57TZSX?y>s@L0a|7Znuiao8^N8F1+q_0up& zqjWZcL>BK(6hp29+F3F(GBQ9P^C8v!;kl-P{x$?8PsSDplP5*cz;Gpdzj)sA<0ERZ zaFOyT;TrDn1E|Q@?V*|sF6+3#h$sUtzi4B1C!7H}kCz|nqqzwz#?3%eaM$8ktp+zO zHpX|tH9uoDICC4XN}Qgi3!4FV9vQ$%bbEbbJDe5S1ShBs>G<7sIHZmcXLxrux<+Ti zc^eQ@(ajsmby}$sO<15lk$Js_dS?hm!1|sLX#K2SH3*&YQtHCwpAK@|yCoWn{~V_9CrGOHG z$7ivG{%&9Thz2xZ_!^wnuSkBhkj`jN=gVdT!^A(RO2WY`#7{ z5tYl3_x`)hzEwgJ@tTquiiq+5Ile)J_#@za2cX>1b{6+c9+BzK^9>(*T+vu6nS zZ+TU=_t1`p_8BbX!8$%g$4eB+ zkn}N9(Huznh{&=CNlT3O1CqW(ps5g&zDTIB*pT!RpdlBMK0idD3`tvoXCUeC!Vu~n zl15@7j3G!`=`2Cg-{)}|14&=J{_b`YE>j`TiR`D@8aJt6Y4JKg?QC>g-3$s?F+j7< zctErmt?|_MZ^)j4sJCO~#e%4JN07)7LL2ECPMFdhh}sLlt^`w28S-UK=!pM__r$BM zjC=)+?l9%O`oLen8g&9JS-fD`e$-9Rpb8>fqFx2zlEZw4v?8S+vx2FVFEMQ`psJ{B+9H0^^Tg z;}BkHXDrVB)POiq@*HKN_J?9c#z^j>qCLY%z7jzs5793}(Q-rdrggNBSdBdlG(B^< zvH~dm_!O=qnXbX<6%ZCQ@h24;Re{3zRCRVoZMv~zWyQe)dfu*8j-EFS8uSAcoC1N2 z21S8D-;3xR)*$Sh9&1p^<&po!gh&8`PTCVN9gzW@&IFjKI#F#` zD{!-16V4EV0a^pJsX4J~yfFbmJuFgu+`W1}iY#sVD7g{Xg3)n(gdluBW*OAd)Tg0{ zM{j~F*TFRdydk^Z(lJ4hN`aG-+H~<C`wx31CnW;!g`=AZ&UJ1zPiU9rAJ!LH7 z6sjO%5$cuTT>A^<(x3w`kxD-{+C?V+VF5bPDP;)a!az~iXDrNwrPHqtxb=Z!Ysnd3-;Oe!(fRIq096F%hMurXtQqi6P3(W{3d2ltL zXvx9l0t?DpXDne?t=S@n-2)Z$AX;6vp6$ibRiSt9N5;qxQ@tA%^gk&=aNN5nxE}Xz z$)Nvb5yWyYzXXL*%7k_k^uIkokZVAa8=>&RgZ?)MK8eGT0@%UiuOo_b-=erm^{pSS zxlS4qz(K#BUrU`orkxkldl>|jBq;=kC}24_{64?ygy=Wn5BIr!|^T}eKhnE>>#^m`SArXL$)PF~4Tkvw4_ zYI#bIglc^XM294b)M6JNn4q);t7)ad*qDU+lehNgD&QgH&pFBEaGTrC7fv7(IH6|7Fp)hu6Bpj z4j2%0^HeRKA!hh(V=#)t{j9O#wPlK{%*#c&1>V=)I7~2DC5<+_SKBH!Q_Pjabi(+Vo~oSo!I-RXwSmW??({H zgY&ykwA|pl&C*8I#&wYg^{EH7~~N4VB?zBz5ON8MGn-P~P$Fsc8Ae5y3G zGMUifQ4#5{BV@@Pj^s;HgZ@yA2aavk4IM0#F;AlLdNe+TkgctpA~ z@JVMd4@VT`zD04B>f5M@R8QHaBQj~|bLQvZF2Y)MW^~ths{&`}_!;P%H*ejxW&OI1 zqqkhORZnbXs+f_LJO&tqadJn5NH`(Qt_LQhH6I}fal%#mVZgSDD13R5E(kF-s)!s@ zw}J4ynA+O-t`n{o`%zZ>wQ)m5nOBa|skQtF`_Vm4WBOkWh1thToWrxetS5g~K>gfU z`{}5$D$%i)IrM(LR5T~_ zeobUq480{r`w@D7TA-;g^!}t!!F3H6BlP|=pdmN({#b}WIrO#y&xGFhL5tmo-bgG= zu@rhMou$zGDe#zs(_jv`d<4yzxbhXv&`kad34}|gko*|Wa5%XiYpBrsmzKN!XKoLl z3X{lA-XTyFCRwHw7z<`@e>V%u&j_$&gG`RQD^x*@yVa}y#NC$$=tSR=T$H#Qzs6yhQp(u4`{aN)QS$7nqtb^QQC?4e5EboN z+}(~Kl1JuUP_*30d`vp-W;agn=YSRDu=}(IyHDZYZWovL_anyIcKZ7ru;Wif`Kox| zC|Xp!|Kx~1WJSY1?6IPijQ3v=K`blWOHm-Drh;zb{dWcka;;vn2?{Sf-hXT0lTN(< zrih~4wm0g-kc<*z}Tid)0gnd1w|o_h`D z$M(I;5~n^G3hR$av5G(Y64D=CFLqbmkp6He%OQP#1!JT6!+bet5H0=K3?Yi)S48rJ zF}&p|IStuM#qdk;`|7K9A-D6;ZWVVP!k!Y44@%5j^7d@P>$oRz%z0DLC|9NaXbUH)G(@_JQYcT^@d1rT;zT*)=-iAlPo{|kKA7r zK_a_rdy%f;gee8af|2{#fXTwu==zvE{3ALsZa0&Nr%=2;K(~!WIXr(2RS?5-^(q*i zTjvv6Q9n$NlL>x*fF|_1I23^Hl zWAA7-=I2K7ehO`^!Ub(_h08*x9hzi2Eh=aofQlj8$DM}q=y9i&3|h~PAeK9C2nABg z3R=4%n3x<>^2h)|u6;?ZGRZVqB9vrM{zXq5zUb-(G>Ukkp zMTL-q)u#aAxxuQj%3TMm7qT1G8iifJt;Y1OT2#DxmYk4QE}3mBH)K_QX3>t|p)6r^ zTZewUQrXg0U&75l322KOZvHVUn93mE-m@HgR*)3&*@*Ke?3evsFyUU zA3^=$JF{L)VNidFP{CzlF@pNnfzWe<`h!9Q%0ayqcqXWS9(=C*pdN{ZnVo`qWfUl= ze*rv>4eCeuN^4yC3G+^EcA_>rj>n_GvAY#}ou3(Tj8vDcW(GlWImi%{aBV=8#$y`p z^wpM=z#fJ)!NdV!dH+#^n<6-8fB8nFYnbi*4d4q(sKG;UM4G}X5M&oFvePVz%R5ykf z9v>*`h7V=oh5MjwD+Y!aj2JTTf_Wps3+83XyH2p4@{-cls9>A+ct9v9KfdQ=I~5J8 z;I-PMREG4;uv_6^rr8}WI{0uK*dtQ{&SsjdL(DE2Ddpn$=N?)Ifz6eD;H$+u18mv8 zVwHU>RS;EHy$Y)A;VEvl=4PJzlzuWmsiVLj3lwz~IN1w@zKK+%OL`AN{W6$UH05k^MI%^OL{&C7F9$z!|Nh^14i8Ynt`ue757rmUjp2O8K# ze6Px#5v?-Pg^o@L*!N6fQj*AuR4u6jqOWv?MP5oCspMXFDj2 zQayXHj4bji10*iMh^0TAv1cz0d>a*?A?rVnD9YWAlI(G} zN8R7^@dy&Rvp)(&p|h_8I|51LbWqi~bTcD<>zhpof$KDK;i%Bvune<`E-73KG6OR- z-1ecaq-izaXwfM>F?(@V^3V7!wUuN6?HZ*~?F}Yhjo_9cbY}Blm>RwuQH#3~Wfawo zMvnLaG|eiEE}kDa5uu~*Qs=j5Y{LxKOd^zAS^?PK3)IQL{<0Z(ld}qq;qhDjXnN|T zd-o1aopR^ibjZ{>kdK$$3t{+FtMhOj!x(UQba%ZyHQK7*69?~~7YFa#Ru=&DUs*(~ zh%c|CB?+VBa7EJ<+nV#WzN7$7f$k~FhH7jRPYXQ}$}0D#Gv2opfGg}&GGMSkgnEWA zEMvwxO%SUhS;qu{Wj$GmQb;8T&W!3n61#ZUnLPOL)?#$isnGvmr+@VG#k{D ziM2p{>P3FS;L+0OWlC?AipEl^;iYLgI1GPSsNiA?i;=on4K(DYZaxqqP)^-gfv3UJi7rI5NsyQzqg#c&uEg@O|>@@=`aryonuDIM^OtjX*Z12Q8U#l>8i77)*YO z3`VWrT&$Uz1pFf_;Qpt2md%D`z){HoP}HhIIw}EY0HTQG_a@bIdVnz-Z8DU2Dpe4n zMDTxcU+f0@I*y&+C*y~I{JKnps1_Q$wnw#BJ=YMC~k$q`fP-f(P#5U(r5FsL=wjc zrDWy@zg2n+BmqH|9|OPB%+GrR?AU%~W&azhAS%0h6;yUF%fpK9Jv04D!|@*j6go=& z=|ItiDEa51Z7U2`awCk4lAAY@lAD*MQaDB|r87VHz0!*Qj({*Tik=^*U{TKeERSfF zkw)};qL9YHWIrm}v&_#4jcDg=ITQ^#XI|##x|IKoF1cMzRVr7b;N#vkXf>>NZGyjl z4$6oY->OI{Dxq|CL?5uCU?22YQA#G1u8Sa+z4`Sh3=`Ppc=MjZoZOzDn}+){CM!er zS-8&2%P%pkDi~cb(aUtr6kKv=fZPSxN#~mxYk50;R-8K2E18S^f$J0ltv)h9pDUn! zWhF&S5$%OJzGwE4i`0kn`N_;&ik)I(&e^|P0t}$t=P`* z#FWbZX?V=o)@=4~Baq<%!pQ^sgHwl(&f!jW1|IRbnAiVl2YCF%0;(Q;rlbhk| z+}!h&m--&1k_zq&Jk96R%`~Z)zb|>gWpl+2oCeu3FSrECD(|GfLbBU}H2To;4wOti zHNF@HLB~ZhgxNmJP_i6(OJ)0x%Ju=lA`9FLv`V5-&g=|JMRSr-XHr=wwWr0Tv_}Ct zHWekkg_Slw2;_@)y+n;n_&TX*A>sMcs8&JD-AFywkK9d7puce2&6rSOv2!;k01dgh zo6!(~a_+_oJd?Zm4cPqdb2msVcs-Q6QG<_C3;V)jH35cmH)nC~M&CqH9c#?DE3LWO zczv=yZdSf)C^NRWQTpWhNX%gJ+<@rNd1GH;AFQEH(RjAyr2k2hS4NP?&fCk7uHl3! z%?Yc1Z;~YM3ovHgbw=IZO%=q@Nxc$6r!JEup9|22dcjGO&jgCPab(#f$rqq)D+b2f zj2JRei+LmAZRTakBnj42t^q4n#;0_Rp&2lP$vXpr!J?cfc^efCCQ9@IES)IPy90E> zMCDHaBhda9-det+h8KQMHY#L8)GY6Bhe^$h9FnA-8q-0p$f0)?`&PEoSa%Pi3Zm|+ zS3%v~-`OKTfBO`z2vFo`?5TmGuEr+cg{~=)1~~)Tw#>7}8s;+^Yu-p2YhIpPrh|=G zI;ED=<6OqU!!20lZJuMd#80E3$TaK^U2Ch%=ED2!CTDxxTNJ4&)tw-;M9#G{<0Ky%mox)Kf2mqkIpl(Z>#h#&tJP>u;56bopbyMO> zt-se!ZHt7U!{^jfqvK@Uj*VmpQ8&v_at!j8Lf!0Qd3*M&eP#hH`wY%!gpNw(n$DFd zlEJF8rJ^}t)#;IC5v-CJ?FU$OgFsUuSaqFH!Hv%rW1;bJKtnEAwLV0k3|3izXTYle z0z=k4ScSyG97$l6(pdtlev8&!9eEPGz~ux6tLy>>ZEExYD=1+GTXHv00;;tuARsfL z5BCA8XQM$PXdyj|b?VErBDiKR?-@wfFdLZ621OOjc-ss+eL2qMr2&eqr^XP#pHT%7 z0#L66&$CPT>TLnqP=^@4dUK$t>${ePuigP|TQM*gV8oCC1I!x<3@|TC!dF;N&9Q02 zk=~nV2G(HmKtL#1ls#qC#*i1sq4!g%XwMdC{V0M+9x^|GqUDCnmK%8kw~nm|LUTfI zbyBQ+4eAtZ`JJoosI9EH*Ewoq*pH@-747t+b+F3&wtO{;inD(c(L=08*h4*5qmps< zslZ`qLkg?YNhpj`7C03?cNu427$DKLRmsOdqVd3GFwQtcobg-Hwth)$M-N z=X!QX0LR&S<}S5%M0-4@V>38EiByO&QPOgZnE-ovF(yZB-R>M;(}YW(5d3R3=9}Yj zo5fET7mxT2)Y*+_ z?}f4)(e_tdb|J}OzI5~~lYVSw2nuSS8_5#}wU(#kImlirs68>iJBSu{Ny!o{t0=V5 zuJaJi{-+W?v41HME62Mpmx|`ZyDy=#?y3?`rP5>`D!c_;)PL#|{$7b1nee}nipCOt z04YC9+X{Anc&xYp7yqQ93fP2XV1mJMV=3xmy3%W z8X{1}MXbQn;Z3p|KG!`ig2aMLLAZ!AdjtyH1CL{Ik+lXFxwSSu(X4ExnVN3Esf@!V z?`_z9O;_aLxs_LMx~8%PtYfR*ZZ!Ak0kDuJ%*aU|39<#{e0V^_#)TVB_8^;TvCm~# zd9h%SEfFNL6MhrYWhezNvR8-So{3WsT&)8~$6|+Et*_V-dT7XBND-XLW&-S4uz)d> zI#m!c6ZI;HnH=Ksq1DQNXcUE9gC_@QL@iU1Wd^sKtnSj7Gpl0w4CX)fNU{PN9GfqW=3x76vUPfhTtkIZO z=Yqn4CF%?^$P=na0I%ez&Q|I(GxKfA2dcXKmNX!xwkaP*umADBnVN^+9bnP+94qoW zsDh}->QzvYmmt$xfz=PweWbXb4$$N%?k599UByja1cl=R>EyFe+_KM#YuL{yu6ZLV zu6elzPo^o?(MC9(E-Hii0VjFceAdx&hrR7-R`exQK~!}0DyZnR_lyUj zu302iuMePACF+2{kH8W-jLtsErT0&Z)o#e>B%}c)^HaE zEQ|qPx<0F?hY~fc+LWjSTGAG@BnlM2D?(JYenN`UJGJLcL!>PcWZ{&#s|5 zl{1>)Wx&ND;9FEyRn8cLKda60DODD7f_Lx1!c*<`91uajN5-1<>g;rNwl*@}m|1(t zn)5GErIjBI#gR$m5iga*+I!|_R>9f8)#>`|PE}NKNX@pO-I+R`G29wabaEzgq|w~5 zT334n#;R8sKF>lLuh7ii%RT(RB40$2oB4!dlCKAb4&#i;*I|U1F?+*d{_yc8!`IP-9eLJW!D<*3a{I|VPs&#Y-QJZ&J$Z3B1MFrP=`k9 z6Dwf?#k#Q4)O~?pq7&(>mD$>E^~IF~+qc&z;QRRHv081mQk|GUGz(6|c3LF;8vs?7xf#s{CAR1@+TwKKy;RA?zDkgf+X15B-mdB1dB%b0ch2H1E{#TJ8{`Bcin=a zq6gmG0=?-LF1jzes(1au*z*8d60wE<3@ZhVJ4i z_v0{;*)e+()Us1vaZO&;tg&Qh#3a`IiiAA~8Rr*)_bz9guLRlUWt=UH)%B|8H40?5BQa+(ikO-9%qW4HebJDfDsH~G`#!Ki(h0;`}UclK+rle2lA4{K?DSf_Fw2)HY z1i4_B);`R1NHOpiF4>I_91c{8L`~>M5)|3Kcy~=H#p$s2nH+5EXT}2^k z{KE81Do3O(Cgaljr|Ac>^hfM2?gR_1Fj#&FRS>~)^(qLKTMP-q45Hqr>C6C4=st5g zb48%2i!GH+XPymhTlN_)H|%HNa`Q%l%gxK9rOq?#cf{8)RWW2nc1# ziOr={G?>_2sV6vhg7s@iI{gq z5XqCw+flrsNyfvTj)X*vKfi0u7T(w%7G6T{ehfbk{)Hg{tWZ<}-FHA>VCf;|H3Wy_cjA$#~=0m2qwNStqG%*n3;pT+S;z{+6q z9}z{lpHXzB`nh<(b23GHho)0{kxV)J?qVOw2*79p?w8l3q?0LAQZfbCie!>0=Alid zv>*xbhnr17hJGj6l>e3a?<}2iabWPI(kUG2VK&kkK;D%0*KptlW-K_Lq4Ft^{@^RN zVNn5PL*`ql>_!Da^#;^z?yk3-gbY;0vLge2%B3+oy@y_yA#3<0_mu%M05x#z4AkrZ$E-v&YE=46fu z5h&+mtiUrlnUBNgy3ffVvEXe{PDbf3&tSG;KLci)Hxig_UWyqNqw~257p%`vr&68Rgv*YAfKZkUfuU+fLSS2|XwM+$ z_eK!O zdBp2UeI#CeuV>T?x%BhYD>jmu&JIFq3L z88e77nS|R@-rDYZdkVHZ0?3G44`5%wqaQyo;0E zHD80h!rUs)kNE{`-#tV1-P6K-H+4Al*8NzVW=W#(HlVP(v#iEDCn#bst7O>N+c{pn zTa|q^wRBT^Zxy9=i$_jpT|VYRvKg7%vv#5}4l`7J7S@))iQ9XoVV}_5)GbtEFUBDd zWO=Uq1=q|gfF5>DG(f(ycv43N_WHnxt5uZL5vy;`!*+<-DlGh%sA~VDtGc#pUZuL` z72&So+j@E>14po3_iwASa%{dnJu%v9SKITgeBh5nIJ~!WN~S+X+y+u$pVh<8rUiF= z>O&!b&u46Wat9nsMof;v_Oy1bc?BNbo_jXgQCU8c5M59O7>?Lu+;44hAV?^F8& ziCP)t`>s?p2jqK@$~sHLkIJeMlW$2q)GMPkC-u}P|A5B{zOzjJzEpH7>d3F7g=X`Q z{8BCZM}95AfudPZKYYqhlRj}|`GddI$L$2J=Vm?m>S2Qie`R{5yK~mo3ZzfTLch3# z(61Ak%@?|A*%x}jIcv8_jdvk#_1QAw4wprwTe1ZGK)QEJa(HQ4?a-ZFg1f=sSOB4d z8rrX!_qkbqTc$%-sH<*N^)WDyF%2-Ft?R<2IhV*d@cv( zJ~A`C?M*&}Qd*jP82%wj(R;fW9C&5U3FCf0w1|FX492~hqb6EG0XwPd(=GJpChN2H z))cJR0RLQNVEg86|bUkB?l2?KVp`TwKkR+-EXL|n@8B)0RUts0M!nNNXK_UY@ zZ$Y|-6Q(o=*M0~(O-CFYf&|xhkH8dK8M;dO$W67Hn-1|&f6h0nwBn^zYs2c79jbp) zI}ZXg@@E2ET10^%@J~_&5dv4Q1SHCbzz_5J(bHD?vC$dw*S;N~6BUMG@oxr-E(8|; z4zz7W!mzjzNd{ywZzNdUyj-5sn??eiyb>^yuoV?Yvi`+_;~xu%2_?$A5k5jigW9^q z^QbC_VUn`mig1gvAogIX5p^%q6<1WM)6*;A;D`;IHf+6a{naaAU04%-uG?@U{7_z- zzh@!kqH&0xdTL}x+H>mT1;@>CCT*9pmJd<|QOnhp!i5lSBhT?h&!YB`OyXz<&8fdikN6PeSnTs2)^dqP~NEKq+VS_`jH6M z+1vXNiZ|r#dC=#Yb>^NybhT+JtmwPRhv*Dr#z9BbQ9i*uV2=#k ztWzHr-B*V|K~6+%RsbXLhe|$Lq8IMF55&FjAEn-shk>$yjkzd7XZ-LVH=*c`4yh0) zI5iRidST#hU!llb780E3M9T@zn}G0af|GJ6+CqT#b(zV7OpiL$k1(n3GCghsea-av z9|~o9j&zF;0ji-Fv^+&aA{{Ab!|{{!%1m<<;7tY;O5@VFc6$tUkTS2mNawhWLEaO4 z-%02AZ#kXgJ@omQkK_Z>IhK#4jVz_oITrX?P|D_65=Aon{&cCR6J_g8z~sRFk!2CB zmKf~^TKzhKrowgEuMsLNDq6i82*^dNUlpQGMysu~Gidc=pv5lHYNQmL212Wqwh~%B z3XgFt#-P<#T!kl|(&B;YPMB!tn>CuJ@mNK@a6m01XziK7LqTDxha%&RW)qIm(JMY0T`z?XDzju+aTLkRWN)pqr|#`Hu@0e(4nCR+1y==5&`q}%wN!Hb8ef(Txy zS3&S%!1AJ1#(m_A_LwJxJD*YMBLhWUZ@%ne?d8z66$L{XMidz+!@QB84D&J%b2btv zLZz`4h9H#I$D-1|4D>h#9vn@evW8qi1`ECw(JDt1dSsemkclSd)=jq>a9}JNBfze8 zxKO*B_8{+oV4wx}CEzV06A(jaOI4lSqqdCPx^Ba^4V$hVfTRtc7`t`bx@|XaRRIDV z@TDvlz93V!8jRa&t%r;MVbj;iHc&CJc3T2kY~n&=M3zD=Ez?kMvE!~M1?U3f*rXiy zVW2~B-0`vOxKHDoKi_|!eV&Q4(A}h)ya-Q|x)8@5&#cCEY>eN87inb|&83>ib>7vi zJhewV&S2wdIpY)bgU;D0V!%YN)LJ<@QHO=)kocBvdzAd_Xczp+0oBmnAG+XAfU@j@ zZ(jJKGoRgz6Mk6wy>i3TkBzR=r1`u^ZqO08+$7IM#!`;>aXIo=xh-ealJ(f_Dkb|& zTu}9DiA>o$e}z;u$2gA7zd#iP?9{F#|qOl}* zx7z57(kEr={!s}jYKhl_LbLg+ja19gtBrmtHGU+(E}n%9-|DD7>swkkoY5l~<2R)t z;j$RNN#mm*@!K&^%z9&m@!OF?1()HzuQqxC^jvQIc36lyIexR!&cttf;B#HZZ%C<* z-;|M~`0a74b=ZJA>tnJxSJqh(N&}5s;MiN;>_RZb%ZB zBPoluHfdV~!yM8*3h5f=iRp%%kgl7xNmo(icUA1#qzc?Seb;=w$p-ZfiQA=_lo)VxFb&^BF`vOH55*j`Y+O{I$(9nn^ z6B?Q~QfO#io+}6Vau*x1bV^l&VU6EYUSiskrI#I>0S?LUfH1KrFKen%(crSCZH_Nv z7d34Iy9Le=AWLxHEPzb2uzYeBvqfmo@P3&Iz(f=-#qprN-GlN%%K7s(-*cK+$-HMq zl%!$r32gs&*02D5M zym=$(ym|SEg?6~gl^z>!4+y>d*!UeTY#Mk{*4uNPH>&}x{!6KXsQ&6z zSpAC^Hk}%v$Wi~30!0_1{-;6PmU&ix!+b{l%^OMm&C7)>NwS*1kXAtHk($yq&1$*z>1L@i%xMF@*~6ou8}9xb_i zX>SCv+_TR^VU+4wdq$055y5^+_XNB)K+pmVTHeKyuL^t;M=P&UdU-@q?pqXBkNb9M zvkHftn!&nsi~4Ewo5t#=BS_>P{Uj8H9^DAW0@8`;kgjv}hMU&o#fNy`H5|VR=Nzad zO4SMSO^wsKl5-EV;C^g+zBUINy4$e(XSy~rKqJ=Qz?(_rhxQLnj;4(~aF2 zZ5S{GGTrvjU0SI|2gjIeN=w(X(p_>NNq0Z^Co+oO>X+UnJj$56wYMC61)G0_mqQ2#d>J28xmF5ahZ#X)l7Dt&!Abqslh(|0Y z6!+QBZU*aIOQ}9y0muS?C4$vyXE7m0m1;62IaG%9ei_^?qc+Q^B~_lbBrC0OdiE77 zLTY_58Ho^vKkSYG5uOuKD_Vq?v!gMJm&39M=}*uhKpE!%Xxveot-*ddz@LWNRmg$W zTaA?!xc+uTlG{~QZVPML3X7VA6a6CC_JwsM2y0zLt!QDLXpQ}<%9Y0O(>0+ul6)1q z!-}G)qGgmS3?`3>AlYa1C}8xqh+5H%4#M@rEj$w3Ws{!?mgFwWX<<#vD%BWFS`kG1 ztR4-lHX>?8vwCTLrn;jx+N$4!>c18LVe?5ZK;7-W-jNF2XA1^}&R$oryWi!{u!2}X zyH-rp-eB@a5e)lcItIk_w1`^KV!C>MZn{y0JMULjt^vad7yRNm@@5jHjD#wpp*#{F zEhN*^tLPi`pk3n|^`b2+{8wOS4kj;)5Th^rW1-fcN7O11e!jnx{0SWVl)PsZxD-05 zHa-(hu#Vf{MV&vrrP{1F=HU#X`b-Vh+Rx0XRen`mlcReGm(SpYiD#mXRM4S-W%jrh z5SQ!RJX^oJa`U#UoEG4cXS${Uyo^?TY#RM5x`-KSIiG=3i_np-PVcVnX;o;s58e5^ zd#Vnb2FBr>G5jco!tj-`+5n!(fs}0C)1CqwGz4wV&ciEsbp6(wHVrGv9AD1)780wu zF)rNyNZzd?zeg$ZyCYQ6SLEY-eG0mvYm&y;sJ?k|Rpr(xxJ&}o2~PcO!m`t`nR*-D z2z=z?8@>(w2c%ZHrCqdVxu$jolTVlCdJwq&L_{qfzJHJO7P_ftp;%zZHIeyMm34eZ z7dol*2oCPT1c)%PK4@hT+lUnaRUSG|*Np$P(&(y1D;jEPF!@aclfGz92GRUFqE>-ux-;#ll-9K8w}F!a zuLjgh3=D>qSxQRzA#bfq@&K&#qsQ`Uz|)@$uX9!d^7^{&4&!Te&f8II!|lXsH6Vr{ z;kAG(GAF%^q#IelYQU4zZ9yX5tj$uf&(Ktlw&7d~axH=g^a>(e19%aXRR*WCW#MZ8 z(@bVo0UnVpp{#TEg&AN3%v~4B6RrfbJSEp6d#ROxUNV;^2fH;V`>yL1c8`@Pme;V| zAr;M8VRuVpSzPiZ38EiMzMde^RJi2paY6+*YuNWCU)KWxxl6w84pApB`LfbZFO*2m zgBH77@`aRw9i}ZiN}Fk+)A{gNp_$=}t@Tnabd@w5#< zZM*4{bs<^&rIkf?8_!TUkLPaMVQ0~OWVj|n^xg=TIYaPnq-&UMP$okFt))?(&hP6Y zmwyZ}Z4=#`<^L2_5VQR1m5|f&&!-A3a`{exB6MANVb_C!qHa>G?4F~&8}qXh67K#I{ECW7x@ys=M?x(PCNGWPkdXmq z?LZjFe-=@TyAI_N)pbU8_yIJg%7rXO05~D8y)2y&FRsL}fp$~PAk4xBI3xtv03XY+ z!N-ByKEVbQ@v9sT=HbGifv|xPBV60W0w9Cq{g#F>8;?7=dW;r)BcNw4TJTjUt0tFT zY~k?v%U}hErQfSDnSN}B8(HHYMRJ2Uf#oLoAu^W236^PrtCWxh2~saCLXdg^_tu*x zd@7edMQ}W1Y+ygBXbv{;n@Hvn8<3dq2R3k)Kz|`NaJo=oQL%xafE07Ffl7!v85^+D zPW#Zwm*8_M$VdLEl_r(U01UDfmi?xkxGJ;`tfX0!oVYXIL zh{EZ#hRYlRj4{d0H*dJw>s0E;)R7=du%7N<^~3ZO8QRAMsJ2ltLjt?0f(QwySAxe~ z3KDp3fFe{Jh6J7+DC+v`Wg&s*L)(^lh6D`r8A!mqkstx{@>sd!OqX#x+h@O>u^I;lK5wSN!DLxPQSN^fX^;CqD$u_;f<*513!o_U z`Y3k3u(tk&bf6Cz3s|bNyNbt(!j*KecxXmJZS~n*)oED7jI-Iw%1j+r7Qu3D*e5z! z-$6c%wCwa6{JIJ@dio`!TM2z(Fu5*5A`A?$C@^lnI-(YLHOeuntBtJj18Am|_fs6> zGccf?rBc9v_EF8)&H@8Co&;b3AIrc%3%KnQFt8GjkkShZ!mxmF`J3B7E-288qcHss zQA}HKO3^89aXb>#JEN$_P{SVuG}nb1o(5&rEZ8TZIOl`9GSJidA>KnXbZJ_6Ad(LR z87v>ki;<-i$Z$kjL)`fG_k8D4muRMeT_beG_1Gq0wy4rx7H zE%6bF4w>W+N<|Av&NpM4Jw!yLp6Ul8@~;B@g^0+vgbIs_i2NxKkc)_XBSf8yh*)W- z!;<7l&|;T}2vQ1O5v`U`!;Rwk`{A*g(ZYzxrQlou0-~-yRXb|Iy};|Zs?)1XI$;FP zHKi*9oMl|vbS$6+V`q|Mo(3cjCP%?PaVsp6CnJ;UVAI2~@?zl^XGM_6e%rk(RaKy(t+|y3k7j+*QJ)!yNmH>SY z^075g)QxD$A|JOw+g22ed>Bz=kPq`lLO#sP1s#BjttcmgbuQy&x^~nFr`86$)NS=DsM{vT4vh#2^;ZTca({+=!ELAtscAI}H~J~KY@T`(-l$9Y^B(JDu_IFm$0 zwu4E9iuMe3{9Xi+Jl*{(6b(*y-o~l}H^G)by?q0Qhxu&`zI_DV!9(}~f(osDi(2sW z%Lpb|(#S-QB^?D9o$&Oq=fiSd4n_0j+&Ot;bx(y(f2i!@eQUM5$7^%AmAxhHBRr|7 zg7)%?3z_~(Rv~eN$+;2iFxJD4+%l+jc0?`iClo?dKNAZ(-`Dp`O0=ol6zZnibhBLYGoxU*@H{&TxZlv9qnO5hu&Cj;X?xq1KFxyzQ ztKMu^;QC-#N2kuunBG%S_W@O=8m)GvF^7B05#dwU1HtCL^`@gMt*OTRG+d&KD}d&A zOtlB#Mj)hOs=fnulug%m)uzo-=s$2StoChG+IK^Q9{Jig0Lr0zJKe``*g$tP;qFL8 zT=8~dxCUY+Nt4pVu+6hwpRA6<`Rlw7vobzitIom}t@%0C|9BGnbYq7pFfh~D1+U@k zlLkFstwXTYT3zbRN@F*i9?+Vq&zWZN{C22;{YV=FDJH{TfU68N#u7Lg&~)k_8rilN zAFX=v_R_t0nAeNNL!6gv=~x+txB;yEisVTN$m~wAB{|3}5T1w3+L^2C3!BcKY0TE) z1jsNjdqQ@T7uU_lWH&5)UzGVq2#!5Oa{}tyYw$IoJQ@naU13i{eIvi3({t`E?s}jR zi%Pbb-$wBj+8RkXp{<7SxwRB(grzHjaNQy?H0to-{Bbva-qR8!Ki_iLtGoBtG-NF%!#hgkN zL@Y+V3Su!Xs2Ic5S)6e#v~5Mf$czz12AMH$BxJ_CToBHPt*|v# z$`p$;o)i!hN|fU}RMx2Y4iStNrU+b$Fe5ZfsE}^9l^p zQ}Dx#gwSw?9*9Ch?u%fKdjOd$)dRlU?9PJNuN+cq<7mW|38`PU4dNMP+^1lP%lUZv zi9SEFUTdu+bI*70ji`fCs>b}&mAlo6Js2fH=nKb#4A={)rkc52+%OD(r zkQtaHtO`hg5EhY;#1IfgjVCiFnR%GabIv3LuliF21&?0!jvIpFg1CSSxS(E96fcOo z*X_FF##L0jxLkMNs_N?PdFpw(pR)vcKbJqqoTsb1tE;N3tG~Tj&6~ON|L@vm?cjsT z4sI`P2MCem*}-ytQ4a2XMQ973B><=juY)_K!f($FR@Pm#dNn*kH)!syfxlLqx9aS( zv=i*G6x+s6t2W+Mx{U}R1x!3|!%8&WqD;cd8NerTrOe&Qs>Y}{^3E5E&3_|Ll^p#>-czN*_X3c^b4=kk@>I3HgLA`cZTq-u zQHeWDi>R7pU%f!pu8`z#V_FV4Ntgv6fw8SZ2DiaIN7eQM269ogW{5i(RkPC0plW}h z!K(6%8Ml$ir$893y)vW2Oma6$X-@JP_$NV5L2|SOP&o+u1O9D_X}KCVVKv?tm{>=pE=)J=DII-rslU1H+j+LMl_wrv@1}&p)t){ zDLQRMWo#7pB+*tGcSQ~WTLf#XUOK=T^ll|%eP*?;(_&1ETb-5!M)q>S$f7{@mqtjM z%>gCdWpgNbI{B6eX4x#>i2^BQ7VW(1byt9)4m@Jst6m=uREb@kBGSI(qYAUO>@tuu(*20p;DaC$U~@PS;^mVU=DaP$zqiqfXdZT3H0p;v$Uh5eC;C7f%i2 z7l`}uDS)k2c=ZQ17pj#M-00REoR3|35%k_g6qwr@m2&QXIhHQjEPd%jr#Tzup zw-|~KJZwSTNseKI40_IfDWv3qo+hMh8}vM$@bL`_Bh!1m24GdF5c@nLGv!?>l#>gA zs@e5O!71QHLU9VYq;vC|M~Az-8Lbb*T(m%|0UX?nwm;A^czIFhSgz3042HRnNTi@l zG0oUN#T7?IHVzR@+qh%^+nL(1wi_XuS_$0%HP4WklVQVCCDI&F^CY5mK+Ty`jW5cl;rz5IPYysk%F1 zll#JFM)HC?{uW<|54}*JL8Az)nbF?o3SE9OK85$64AmND0ufDb3_kfdveTD*44IAD zL^IIpnO`RH++oGjd!X~n5v}Iv{|m_10Q>E{+t~g&fzAg5t+XHsBSa5S1`#1rNkN1t zjc7&zojbI`HpoEd-vUi?XGvvu9PR{cSdlPpWJHp|jZBJ!8=1t8fKDt$1x0E9RB)@? zPXZ!xu%7#gGzfC`!zhl?YjdEoWJ%>Be3}a`7o-^zoYhhDA#zh97+)L?oE*@-RS4VY ziIhRKQI!<5(Ey6MI=~UikFD|i0I6$@$$mgw0>xYlO4uMV(lb;E}FLdqZ-rb_D6Fy9d1 z$T7^<1xPzF%p0I=+juri)A)>GniR<}P2$0Y+Ow8fOb4ckC6+eL=Lf`=T~0L#Ti8-RtSULN zFL^knvM8|mp$NWNxX5=Y;TCI`0ZARNmbws6&jE}WGb@)gObB4se$WUR%sTXCkdgyt zF(}mT1AEI5<=jvm9^Rnd$qgU9JS+=hrON04z*?Ltioq-3aS%=%<72}ckfO^d)`=kB zq8XB&z9WitEYK?N(|U5}C|0Vu83b#O41q$gGT%+7BjoC=$Oa*DWgC>N#I~i7tAz@= zN^3yHfi6x2bQv(ld=qzRJWb+K24gOkNOQoLbwum1=G=j8F)ZgJI4%@(3M#5gRm$8= zNTjjcEpY5QEx>Hr!j|{VSNpXRA2Q2VOQeM?=etbZJrLcJtf?31*1H7$3(>8cg$&yj z-8u&t$VIo_7UE7ux2&|&v&Uo*N^BF|LQWybA#_W*1cGmt!e{h+F+1-bvtk%l#wXZk ztE=i^g{(^JXXZZo0F^QBMq z7m79e<;8lna}l11?MNBKiI_?XPQ=Nt+9s}&&HzNxQ_iqd|z-oxi^Lol4nx{(Y)I2{J;K(u0 z+XAGWnCFL~Y}yhJ#|6=vMR69RQ& z&*80-Cq3TwkiWj=AGSFI=@ywS6>{A0ah-Y2{v}!==jV$an zaSNQLE1(O(ECAj%u<*uUIn-XaDAJYpsJ zZVmd;VVU9DSPh=;9)$~K`HmXx2_mVDk4W}^1+dbW><9mZ0xjO5eibsW&fM;enYY)O z+kprcIlMX&`5H)=Q)rlUlife(R*hpVa8AKyhNkJnG0C_hDIC9MKZ2?l(9FqwkE&=4d6Uc4j*&I#d zGv;VgBy%*09RPV)Mq9@C(twaM#+V<|ASq)dkB=yoXME_wBWHYv6KU7(cl=cZlRVD+ z0!V}7jE9vRzP>&U1NSDn_6zo?tC$@QzTv?+HLRO;y(n5UlDDGBVW|H*G7W>aVH_M( z6d3cD2*I%SP%vHAUP&;4(=;%ihcwxErR@Wq3T;w;tbMde<&$Vxi{54{jdY!ey zz(f6KDJ%$wMZR1`Ut3If$C^85^(Yvh!FY;fzgN+yw-5Xi6)O&O-^-C;_C!9m7v9t# z(OQlmk3hZ#*em8mkpG-`)5<_AZBWTm`O_(bIF(mPLP*>Nyy=nvpBT$B-gHrb)Qz;u z;!RJ3vaLvXf^S5Unc$lgX@YMOJHnf=6ct*eJyXHa$5R6$LTNJAbTW}Xa#+(V1FTwY zuz|jeGKdDMl7a>rz?$A3;K(t>w+2XEQ%uHzxCGYp4j{LUXHztd&zPb~kxbDfc7Qcu z8Kn*J+JJyEhL|55At~cbkBcakXS3+KL-R2{P_~FjyM{CUGJ;7SUw#gx!STgIC>Ex0 zCKdb}Xelq*4EeD6$_J`U0e#8ekQiOKKM6k#jT@R$7(ZkTnkIn>h zttE7O8a>&d9?^yK8MS&H;3fv7R8OI2Kx?YQc{o&tX_YiHz zu-OArl`?lfmPiY^%l9?f!Vor-w9yOLZ0<}pgeZi~W(gU#D{S^Lka#X^wquAp88)-h zPESsgH$!!8!e+=RgdYT(sV+t6&|BfN8g{}jg&xfh6nOWW(#d#uRSaJpQ%5Z6_EPN> zO64*BA~^v>2ZncCK!PTo8t9ShBN;72X0{iCc5XzIIp{hI`5IscnF+eU=R&}g{Bt5` z8w0Jhb94qMo=F)*fI=k&0gASEY;6tji3Z3BS~EcEPB+RTXxpG{D-wn+j7T!Dg-MZM z3zOIpf`+B2pd;<13J|nQ10q6cGJC@Eg&v|pxp!Hw()F=rtuk5G%1oPn#2weG%TaEA-*#ppo}5r$4N-a2--yv zrScpRU3b(Ru`gLcq+LVM7Q8weW4R#{wui@;U4S$=zIX`QGCZHC&Lq+)TDU2_(U=?> zt>QK1TSuECbm^$teS)WKb(By#pNSM&rL#gn{CUS$E!r(;6jp|Z_ zO3c7#bQLiho}S_oreO5T^w7I@4;__Z z{7G`eYk=*(Wa$8il9U)1tf^2LrOy{JC#&R@vBJwrBuJh4_>0B6SrH#mV%Djd$ zh*M^j6r3`*h3Sk0_{2bvF`Zg~)QwfkVmb+wZAHQpX(N)%MB1cC6KRv!5vGHsxYMHi zA;yW7R|Q0bq>SmDN2HG&rt{_it5zFqpf^wk(LhyF&_Dy2&W8dVIi`4ffYdd`^3DX=M!7MATAB7PL3_Qi{*#so6hJjt9S%(J%8wF@hme%NsK$|lhMqj<-4gmPT ze>ueM_CYWr1JYcfWbPz`;_wg`#v<}4Nk?wy*B$i=EgIYz14$Qmm^ zf30Q<#e)XJcY1PB3cl0xIn&9r@ZEEP4FSHx&oX@XHfU{+;JX0@AWdwV45N2_dFUPF z?f|?~+p$KG1%ute!^l&k%a2t?+&}Un{m64`?<@~`;F6MzWs>{*Xu!ZUupLQV8BWqX69w=Znw&XCv81{LZqU+>0$q;dgtcB~6w0J6M^$!pdG9Wxt8n zTKz!cPX@}qBa!9+W#1%Phc)L0E6bbnQNGsdf2AsA?tUwg#&S2CESKeJ`P&&jYYo%i zzHaw;oe=NH+$|u|k>8m?((RdO=hSqN(Fc&sV> z*i_+1ONH;1F1)o*V|r?8vfkX#7>D-?pFKU(c~4GgLyym3I$N?0 zga#(JH6S}Q0u}gldsHE@G?9z#1&6jG+R9Y8Hm6=1vs9J(u%Z5z*~Xd0g}MUx_#qDkxk4#hG`8{)46+RYeZerSZG42ND9Q7X^0 z(RD}7wEL2)iL`5Q=-Pm7V0(Ccxd2Fm zDgqB?0t|KFs<^(4vwB6KO6&o=*X?Byq^w&MSC@4g1(SX(f<@No9Y6{iy$T$P1d~2C z0w$fW)a$AJ@Q8eR5)egeEF}37a@?1EA)<{8d~)Lum;7u*E><2&CQ5lmdRPH^W;HJ; z9v&F@)YAwJe0nHy>s03yaIHCAhuKsG`;*-nylHZ5Y;r3C(wjzWW5bQg)a2Ck815cE zMT@tyLaf{$QgZ)Qgam!LF95OVcEWrlbiSr_7=Z0dXuS&oJH5{aW{;EJ^wASlvcq*C zcLlgd59jBsDWn+JE;X@?yQwzQI$6qexH zLbEzLfm+3rW9s{KUCpOq6LAyQrYh47*dh+^^wp;)Dk~=vf&KZrW%uDTR=cIMaye*ZK4LUtdVRl8y&g~ zZgs5l5as%?WT};0H!84#qk{XAV*-cxU8%u}j!N!Jo*5woUvztc=$;mlD_V4? zD&()Wp}B3U#v-IYL4p7dP60lsJLPbtA9~{;T(LSiSgAFKmP(7O4J)(GinhX{B4J%L zqS?N%_6A`+J0e%Ku+Dw3 zv(Li0(>W{7TXptXlH9Jfa_d?xR)kb~U($*YhA+Z>K!h)e$W&EC6wdKbibKD7CUckOLV32yH z3>UEP23i%{^*|u@(%oHj`*mb*KbT%f^XG3y@{X(5miOcv*o@Tb^}f#PwGlPd-{A`O zuOuGjRoI_Pqz=fbRe_6^KPB3ZSFmTlL6{E6-0dil#&S0=EmOOSJqwexrqvH$%a4&N zmU%poNaNPAj~0r}U&mG@`|H@Vusa&g>4(qx$x;<=YW7ov4BK@z`@f)j<*sJ04{;~2W?N~eSB;W8p}IC#vyoF6w`nz7IW}6hy$e1o zcqY7>eG#u_KMQ-}vnuD0o>`&GjxqXzP+tQRME&8#llg0_ zbvX9btku;2$&XDW7kgtJ+IR)71(X&KuY!8FMr# zk~x~h4wmV$jJAw%kARTM8{-K$lveryK^~|qSyEX&J-)G4#}OV!eFWKS)#0U;vuc~F z(_>A10La9+{VD4Vh3!KD-mQYzIyX=T(K=O9*gBzEI%e1z|MrKj%L5!a);S#@?Zi5- zfU<4l**Z<*GuCNRB$^5 zz;=Zy>#|*y+|07W4aI{$b}hEAzoCLl*_RpS1(yq|qGY2H3Uc=gu+xFVRMllX=3aps zQ2?yi-6Kd@u_&u9D>iB;%c&78vN}%&(tLHc&WPBNq7M8`Oscs%T>DX}ZmEurRpBt; zfV9iy^bX6^gL22^7^6$pq7?d))e&;@XUw}ot|vw0VuL_wM;V0aU|0bTCTdDv?0I;1 zjGn<8wc@4;*W+JuI1E9wNoLdZ1nn|}tub&xOI_`jagdrC+@%K*9e%0uW(m~tAbpvt z4qaB=47)1k(X@N12oI>@N-yrtfa48F2**V?!*f^-Mug@w z{nE;LaPXmy>%kO3(gvO}C=o9Itxt|qRtHC-s$u1w8c=OEYvWVR`8b;4_5`e|TEWZ} zI8OmPJ?h)w;2wZbkYT)vsFNxkxoD2SV*w0WUAA!>oB>*@=20UHFWK+^x5 zqdc3MfgU_T{l0V@v^B!Ba2%v+fZ=qPinda|<((zc zLY94}=EA^Q__#JISyM08Mi&eG7v7KfSRsSkh@Rh%_-Qbb+_lleLfpw~qgL9Pwb6G% zb#1PVBBwA7q_t7y5@>Do-SAlj=i#-{lP;_^A^y}?S3{V(?(7w3JypL>r7o<-=hG)D zW^WqqUo$%z+AqL#iDW$p6-;tnK(=PaJJ2h?PU2gG+-$EC!J8x6%=6-5^iVCUH z{;S|b@N)tpLTU0+(-DT8RBDk*5727{CV$Dal`a!m0@0aDi# zlUsne#8Tq}KyDk)rf3?UF-4OinW9PTV5t$yC~b(J4G5^bAs+3-g856|ib(R8UTnz6 zoxE>maHMI%W8Nghi%t+|HN@t5AY~BEQzdn3p2r0^a?EpCfV30yJORqKjc4;Tjn9~; zNs-LcBraSJSRg*qp?8L{9*s`mxm%e6f*35Nw1F-Rh$v&A`7u6{@;c&lgxNC+jIl)s zNBJQ@j?lm=k%o6&nRP=pZ}Z!TkxcvYh^BJ@G>xJS1wbyU+?wT{KUY6Y?K-h9xhAEu zsM|KLj^LYxi+p!kxFr|UZjNAzwoC>(0l-x<{{~lndgil!WuP~s^tJgLG zybiB-&TxGhuW(18O6)kip7y~AQr0bstIN8LT2K3N1dFWE9|9?8^jXkvg?U43rLgwp zJZFe|Wc1CMu%0q83A<*}b3wH%;VtMSzr|YBIo__+VEU~pxi9&BgajBg=BDHM<^PGu z#i~WQMXA=v7ArvasAiAFKAKm?^kh??8!yhpP_~}nn|_+v{6}G)0A=3-+{sXO;zMS6QX(y6Ip53Z z<{?BZX{r|x@xKZD7ed6Z5Hf66i1=J!AQvKjS%^CsBDT^_LoCS>D6vh57&%3Uj+a5I z?nW5rGWe`UsW3$R*mX5@91coMb0f3$!EW$|U@wl?c#q_h$VgvuC$hOQBJdvQnL8x8 ze9X$F_eV|sGosNP!+ja~G8zO?J$jCs{5sG|8>lmO@e9fzVizh&m}YbV``!7?VH0HR zcZUF}J9{aM{mzE6twWIzuB+4L~tx5`-Z2%E|a)2WgDI4hO0I6%B$pJuI0ujCt$Zg}z7|2sxpluWG5T^OBkFD(uoG`Xlt|;S96Dp!F**Bt145D#k@NUFCBXY5_P!dtfGSb2d z(BY}+NwL>u5KTwz8mTJI#2}iU0-2td1Q9Kg%H6=^&UMfoLZXKGPT)sSQt$ z#lvVv=D=vFf;s@w&Jr1OHY38W`YofwwfY8pKn-pL!}nGBZ+!=1mp6-E6tGVXav;$5 zWS~{SL+j!$0c{!Crl7WcC5dUUO-?i&m*BSH$o3)JX4{txVN+9Z8}9uX(&kNZeA|K3TxXKtq78@I=l4?*6EeSdN~E#;?xLMcn%h(YoKrBAKBwQ7 zs+T$ahD2J(Y5rKHy%a*RQZMcW6#Hj^|3WDCe}xR&6^h*i4CF$wzYB3EL$OxcX~ZL0 z1tqo##UiH=@e&lPTrok8tKqYXb;3~WAs6!a?|`v*d+CH4Rh5M=Y=y{-c_)kC3YGUI zN5DUk@N4e|Ns`7QWN3SBzC9(P*&NY79{C#JA@tGpI{8I`R$4HJk*p_E1`)|pNy4PF z3jk~q;1g$yjBjlYkh*i(vHAI za@%+|Mbr3cujz` z6LVeNif%L>o2p07V1tRvm)3ZH#l4+_9aGv)$ScMmS`(*9O{R6~|V4HDwU3RwV_k*1m=X zrASX-y(z$xW4G4_NIS9HH$&OB`E0kQ`5C)4DU#iq#DRFV8b!5AWCEMUx=P#hl>tF! zY&su%K~i4QePV=L=fw`3Bt|WE^d%<{Y1d9s{4}EJJd^zqiZ(Qp^_FyL|EC^uoRJ1h zUrMq%mr_Bwe@H1eYVr5C5iMjjU<ls|XPw{=0c7DBlmT5~M8ROm5otDFVN>eT4+W4pXI{I-DA>Qxt98@>@} zRTR=2k=QGQ7B~{nD8Bd2^jUJ~w?{St7l3UelH0I7sRdv@Zvl=5?x90@t5DooN40l5 z*!4;KO}sGZvl4&uirHr*(wr5uyNK3d%~{R0yg47`CEoj`DrN4zCy~Z-H`|q`yrp4t` zsSosG`Sfv;9Eu)-IbO)HU6)Tk2qu)fe0ofXJ9+ukN;|z?kz5DWwYhwXoPw#)@~LuU zv|xAxd{#k1c=>b*ztn)Y1T2i>a$vDOx1=)H;oRdQ~!MJr|wE6bD5rz41xH- z_^JUZnpk)sxgHy%9zA&`X5L;4q0zSHz8xZxonCM4y>(5s2`ky{M?et=c05jN6qQwGsURZ`GM4WJ;S2fqz)L=j5(SV$sA2$2aBOtMq9@C&47@~8{@eUQQ9|8E+lZh zvUOy1Xaqz0$`*L|Y839B=4DZOcpd)yYGp*FkZpG2+(KlzqO1BeQjj_2d zrVOIFs-&>F7QcdWMt~#7T$cw(J2BTYp={fDHdoX5jJcW=$y`n1DIMt6#3ijxN`ZI= zxoOMr9~%&N#_;oldn9Fi{>q5%#4r@bE+H_9Z#kMI(yrn2S4T9R1FS1iyrBTg!{_%u zi(}a;TqzGX)kAdaoypEkw7QsR99&N}c?Twlgd{RdTv{NO|6smZ=d%;BFJXzYr>svmZb z|JZ|Pip660!OIVy4seH_hK&^UUdl*|8DQ92PxOpMK~U?#{jH z=isLURL#ZW;{^$xGUKBpT9P3h@c}T69Dv{rFzQ!HA*ulVe-s7>8TvmS+L#CZ+c`_y z4+5xX;NhaPF!rDK3_N7c2mZVD3_Mj5Lj6xA%o`iyK>qMdYjwEVtS&#NI@Zvq#q$tBo~ z)LOuCi$2)7Ew<}V^s`~1u2{bN!kZ7d|H>V0qSPD^!% z#)X88oh+bjmCDg%)G(V8O(WDVzY$*(8Zja(;L9Zx@FStvd0 zKTM13Xwvx6i*>YfBsmnVqpcJ&xc$B7kA_?d{U&!E?Tiq2@;aK8c4i&z45+Tnbu{D@ zCN;EF|2`r{~lP3)l13{x#JtF{)FTZUPr4|AU@HsqS~>9v77FlAu`i% zlLiO~%^#|7; zdjDR>je%BLz<^QR>nVeX>Z&9GF6hEa*#`rBqQUS=*=+$*7ey(%Qubje+lqv-UL%qW z)@xEEtk)!Vv{HtpFh;BFFLtHu^#L)VM0us`HAEV;)}9?3{B?j;s}VNRUr+|oNL5nM zNCPWnJHJZ^J)HR8F~=POq^>z8_W|Q2R?22W*|za)j;8S$b2KTEIhw={R?4u9wv6$C zfQHK(<0X0$Rq5Y2IXR{eso)W+W_`Mb|Bg-!jZF{3b*J$BECOyO$3(3*3`bUIAk8Smp69P&o-&Y>5 zP8S9{3ibh5cbbBwCp$Mzb%lso^GgB^uvWmG;6;={>;x*Q^GfG4LDTo)kiq!YXe z%C^ntPGFj!=>#T4>I5cnaZV@5sMDHxbQUmVtfwtQenCKx9TSSz^E0{PX4Xuvx28ibqY1cMD9P{pQ zXw38GB|sXSH+vf(4q8!ZG~tQnal|4vZi8Lr71f7vtxK(*6p>hCD53(zuRzWKX)xTu ztSSXGrlNgbWIipT^{gUneV0{Kawo)w2xeJTPe*}-AP!Ge3szJ%*CuN9YI9QQM(}Ik z1wAsO9|}yH0rooZO@6f*Cp8tQ8T%wFd_01b6^=6OvcjVdHNGK&MOO3cfHYsttqp=; z>bB9^*f3}i-iDsQogMXBqk+@kYJG8|f-o=5pde-%f|+uyzO-^4z6?fl=f-@DrOYJ{ zSz>U~y!{ld0g2a6PSqyBix1-tHWPp$ybK031XZgy#=tfFlX7RRFjC9q+5 z$+M?x)3qhz0FsQ=W@`GHGDEWzXqFO9g=wlIkA23>$dS*O0Vg^#f240@S2fU%90e%< zCDR*67Nk}rM)uSnTHaQdI-KO0f&hTa)x*Dg5;jF*HTQd^x!;C0H-a7SH%Lz50CD*& z;Ih3Z(uP`nirptv1U_e42dUI0QsT&*)ykdILUmH z*T8=8n;^WwN^^9))@WA8rv?E|Y&75k>_PBJq#3)|#WlqlYv7 z)7UG8Lr30H99Z*ChvZpMG8o7rAXhfqD+56Zy~y;F;)WQh&-Y?O%=aZZ6m5w4 zj*!7^a3>pL4&I>Rk;XE1?#m#YTgE}fOlvm0#SGWhBxeH)xm#ks72;3c5@Y3^*%EUw zl$f(6W*=b?nn~^kGa8wbd*Bq!=8Hg`0x3!p)r)%1tjFmyK56H!|o)m zkrZ~@7AB+ESU>DGG6(ENvL|1-mq*r%0k>3dF9zS23Op4)it!R5gXUJ~cKvG}@fGhSC8F+gxkTv?2#zG<4t18n@S%TovL^9(=95GlTCsD6#Fq z7kLHlXz*1AM1$`|@HukuJuo%+o~^rc^lX8|W5jp0svxWSaM$sNt7JrrAKtV{h-IVgaUIT_NZ|!vE-xb_YbZ1xGvE zmSlfyR_g5DJR@^eu|1KOPO$(&It7s#t+|v3TPkrXLkLGnq|QXaoogQ%NsDuBNdUbV z?pF&u6%P033mIJBWu0%&hWmqnh1}u(i6Q>v;oizSGu;0Jyk*c`FSF^m$#am= zzGPcKs?J!qBj!-k%q_N+--Ur%qr))qrddhwiRbxit97^mpb1y{==Qju43{*Me^~^J zyu^Pk@->h!r-(ds>9ESB^{H`svZEi?nP|WDYP`XK?;?UkTt*%ub;1RtV-0#JV7LN% z2XI*!R-HGEUasE!0BzzYTobO=hek%X)JOuUt$A~~J}n*d+ZW9{0-~{-KX`-Q+bDy$ zK~E)lv7^$bf5Ihjc;Mp!j?kX?EXzj&r0#^G>{*siK-sqOygkn}KC?Z~q)6NIOyZNe zsB@#oRyRw94vpNZV1c_q2Apx7y6N71$(sY}KvF(4^F|^Ko|!owj9A~=W%|v<{xx1e z0#6#@i$=#TJ!a`K;)_P}Z8^F>xSxzD$y@v(&vfWXQd z?9q+sak!9ro3+*p`2%l_*#wthVdw#dEruMNUt8*2{o6=`%=8rj#;vBjn7!FNs%nqB%ai^ZjIJj z?Uw;okDRn+_1_4Hy1dmt9p-=5=m9$gOW#zh*Cz1nEtvaAZRj#Qe7KY%;mP{w=Fy2| z8|&4Hp^+sx>m00XhCI#c=0Uv35dT)2q$(rT#)#Axc82nGSD?R*OsOXv^}gbW)EWc# zgd-_~*b`Jzr#<2H07p(wI5j}pNl#b-W!uJcPcV(o^aPV4^#qf+rrQcP%4~JLXy`Y{ zcU%4D@PJ~<_nV7`VZZ6n}lvNIsuze`FQ&>GmKE@f?=fEguA0*Gd@%4 z9r`)J&jP0=-Eq8cM&{Ikwg#GNZHPNigEEL6NF{aJfm#8MoDOtNfV7hi^l~WMHl90> zX?&&wnG~r5nZz?X*0|ALtMjs;iy&uhb&;un=rdi!UlB|rH+*#R4H1)HKAVF8X?n9x zx>Pa@! z)L*>jORL3w$qyrBz=}c{bXid)4^Zy-{^B43ZIu=F_tFZRXI4B&JA(HEU+EAT?U4Ij z7+|df59U^yab$Z3>P3;Ts`rQ>WmTi}N~yZoDewWgEzo__KFZ(gSy>NY0Ie%EMkc4n zhT+AsXIZ!3#P2LN47NSkt+Gm0fab z-ErxqIPq&Ng|PS;&p=!lBj)9c8nrrL&r8%9%|#Agyd05c`oK6Gd{{J}!H(sN;0XTo z6rJgWrKz#WZR53xCS-;BmM>bnV*L{~u3EGD zY$VvUe9;!F#)&JIFIqM^)m)|uT&4g+u<}Q51N=_8CZJZmq40;GJ?q^U`l|K3`cqcJ z(`sOg5Xup5h3LQ(z8lXEu;H=JZD6W&_!5Y4Vx*G>Nrk5@TQ*o3X*Q=C<}dhz?7AOB z4~LdIsK7D%4hsSqJcFb+GLKxBni|gh+l*dVZOz3)#+r5D-2C=+FcQ!KEv`@3M`w}* zDZyQBf`4uG@J7_2b5TD1GO5XCpfw!rqQ$Dcg#F<2^e@poJ+D)q<|0q7l=N?(qgO<8 z^eTy?V)yHNu0spV`jGXQVYOVW0R{VepcV^?m{v&)wmshKo*i zxE-P5lHi$6>9Fonl{a@wo7#U;bnddMO6XUZ4-6ec^-duZnEoIs{*2NupKZ$D??Z~sON`8zD^!JLl=4c+(hFbm8^g;?^ zAC9aKcg>0Q*+ZF6?U}*wP-(Z}&BCgbBeFa2oR9F>3Q_oN-Q_l6E+Ox`nF+2DwbeXUft%;qYIG?vX>v{y{?nM#0DriRiN=!jIk%;~U18q4V% z<+am%dY|DmG*kIJ{y(W=na6*TNMm{2M;K9v;r;GJTX|=;d4C?NYkQkF@(Pn7I@P5@J=*5|Mfi+i zEuc}scLw%N9qYmqCDA9kP9$-7_-Jc4eWJ^j|>nXQup2V3Ie;ABTS` z`|u#GLs#(f1YK05W^lC8MTbqSwjiDHZ(A9n&(hw&P>%2EWv zaE5_5s!i4EO#n~KBfttJ#GA9=ayLylsIpg<;-Mfow6+N@f};gxDIf0G=ff6i*POYq z?NQ$jYcX4t#WbTWCTU=fqtD+N?9A%9?eqA@ZJZvT+Q9P}JVvN*bin)6>gwh*22=3f z`jN?DI7+xUpJ=IDUJ8EE?2Zhyp4v_PAysGSU?Jm5Uao$)N<&M*MQ28wqj-MH6r8ZD z_tB`8=2@=`=u}6Q2rA5=QWZ4QbJ19=V$XD|Rg7v82ARN}aV&6(&=Icp&6ml0C7H-` zjdv4i++5@1Lb3Tlt}3}?ko!5QiZ+5=ReAmxrmX_sk-J%_(;eD1Ee5&Pf|9pGHiE%= z5#;_-;Hfak{kf3AZG;U#dUckuwU5F8y&gZ48}PO4toJ7u2P0VIEffRDm*Er|CY@aLLdoMDFK9QHu9&F6A~Re8 zQyr@SK}zT(@6=I4&vSD4>3uVjrx9jFpiOqu1aEy?P8nd$a;Hjv3KdjI-sA@AfKjg0 zk;97v9AV_kM-DFxkh&X3${snq1j@FJrzuHaVj7>>`est3t#2mrkbpjoZdxHq=rLHT z8t}PC#2yViB_KAGFmGl-JC5AUawL&BbemQ_HrOC*VztP4|`=MYFktN3Aba@ zTk+g)LS&A*LIw6EZ$U08KC|kI+Gh5q2uZNIP!e5MSIKQ=pNwFZ)%I}|NGTs_4l4^j z20Ria8=a7Q`+9&K*Fz+i0df2ZOjTXRMSLYtqnWt(C0~pnWyPYbx~$l!`}qGF!6K{k zPe7Wl&ej6Bt8KbQx3x)^>(95zI*M>V8LcLJeh{kZOLm8U%7qJaA=mtfTr6>HPL#xr z1!D#11XVneAD*KH@UA``z8JZI3-@;QU9t?8BF@_czG@WEkUE?Y*@72L@ML?i0%xq3 z9*a9o>afqPK2aN<55!2Rx1YE{1AO3to(ODb_Z1O(r2A_p`-+ayXk-BH(x4^)UWXR|Ub?h=uBN$+CfveRsnGtkw2`eXN&Fo-) zn;Sj6vM2}9*W-OLkr97#Emqu@yafJZuv?I_`OW;k)Jz$$|F%S$v%TpXk+g_xTj?cVM?qp^dx32KUErw@ z+5U@=VLKz+yZId>7t{V@h*cTWwxZ8q+IK>U9SnTQ{vU!7fH!j}wbH=!Nhns$!NQw4 zz;ENc38qvyfl!jDkh|YB4QG+nGCsL|-d|W*efGucR_K1+Zg$f_l0j$#80b;hlqmGO zTQB7JTIbPmF>P}3?SOb}$NvqOC6vqF_ zh(@v|u#sKXL`jVQ{s?ASBi~11lycnqbPcT=zAAGYEqFyuVN^jL?GFK_TsM_G4~R=3 z{kq1Ct9m$4Df%AnYY#<`vW8J;r8HbT>0_)}kL@D^F&=`EIUP$G9eU6OIsuZUfXtzY zrJ3U3hx2EOim|pgq8(4CD>mSiy%CryYRC$JIq~Hfj*grHb7zd*dO$_0G6c`cQSnIV8+st z^u;rnp30BrMW?c^M8M8lb!shl@H*;F<~}Amo4T}8IhX#Z3{O@jCYx$miWjBqqsSeW zVzih{Am@F_82nRYo5tG?Bu~H`3h^5?%`P5^+2d&`fyWappa>hg5-O5B-iz^j9yX>J z?F1V;K}}T3y1k+exNeF0ey_W`O#M1Tj!%Pdey)x@-y1>M zE=)1ni3>YkTQv+J-3i>B0`nbMmtMZ(7|g3O*}Ta$a6i+x{B~z z$7Vbi?vvrjtg?A*a$`e>a!MD*m$i}8Xe)UviX0vu4k*m=ZvTUAQr_)Q%uJwjly}q8 z0PiMfy2!ho3>8Vfey)x@*?U1vMb?$_WbbCP>iTrkZxRW@IiAx7mrVOH?zrO0FlD6s>tpPY#t@t!cHRPx3QJz+}6+EpmYk!3} zZ+Gt)R3v%YDg2)2X%(Z;b^JP9d&L2Smsj*nOTe7DYSYh{$J`Z$x!H8>44?FPp2!=$ zJkAT%%LTnl2sEfoEUcUEJ* zd1Bri)^I-=gC#dV17#FhYbr#2C040UYxJzeUA!Rnt#PfR3u0~4lDA+hN%|&CHo`_Y zQ@ISKC10HHkE{^4drKAeVraTs;HhwEx=YC5cJJB*_RL1=thX>JLeuEk$8JXTYKv}=TgP_ z7tj3}*;HZRJVTh;e)(4_-5;3B-9Gn6p#;yQ@^7D;^U-#0pL-B0RJYHemsGdUIqk#I zN?k#hybRKL5LQz3hbos#%*6*Gom{`f0^+f4Z5J>)8b9M#nKwEv21%%)d!BLeJVG9g zNtw}GjgZ{JPUcB`{OlaK$c;zJf}@U>DtEN(>ZvuSzR-yIco0*kBjySyqr`}L8dj-B z%$~Noi=*b+xE9i=X`7dM0sIPl0qEIh7RsVa(;y89AL?ug3!7 zM^0@QFmf7S<5!tCa()e4a^21#j?BpUElkQAITf#+jGX;yu5d2AbJVYHQU#zv01{!7 z@?(V0e5WR4Poay>)N@TY(M75$FpRd&H;wA&$GZmciE`e8K!5W?U4w9gEIn}!AK@)1 z{QsswIGttQ2<2n7{tR}Gl9WEAp?~@V#zUaE665fLY-_N%(j$R&aRmN*T-#^_whc@E zhHdmmVE1u6?W~OUQepnCAB&PGLB3+G7Nb3*Q@dcm+MY|E%OxtKut$^q@9>(1rt__3 zk<>Q%fbt;{Y0d%VgNW97&cu1OF3o8sX<^I#dPIncvkCX)M2U*`K7D^}mA|XgZ(GM53w2);#?r=jLclAl~lD(Lyd{yATaH8@hA%oip8#eapw%ufRU?F#+^7#;d@CQW_lvMC@~+B)8SJ&OmB`*f@eedGn0KGt2MFMnaQ6(3~FYA`jB6gNFJaVh}5IR zmfusINr{u|&ro)WNr|=rn3S0C%dawTQgR{)K}|}$#jca_bKZnR@!83QZ>MMu)@lCna579pbt|(~`ZMrqP3p?N2V&25dXEEVc^B8RY9(!@D@W*bvt`nqJtZ zCC|iGrluFX7RDM5?6Ah@O+6h zCsKG$BrWb!ks8~JNa3vlPlb`fjY0;`%g=>ivAJ!kHq*06VG>x#jTCMO@h3+LR^FLN z;T$Nj?MMN6)scegFEkXL2cIJ$&5k04FOoD$MhgFh%&D#`MGD`cGCRRAzbTa9*-(C@ z@KeZIK2o?3a;ZoG^^p@PJQ0!@zEooKhi#WZCsJ^7eGUtVhcC4aK%`(isb6JYq%h~> zVx%x1Kj%dXiqB3Wg`?GQdI7x-8VnUAP?OP1RYHEOu&$c`rmid$EcCgpm~l=7-FqNniE5;B3g$#^QdqN9Pz)yl#-3v zPAO@>*O*kd%;tzhTF9pF%>=_A!B9uiPA@{8mcV~usB?{w!EJ;chk6$3oB=H4hB{Y= z_>)5&EALFGvpQF~@aSC+~g3sF{)cG(;qhzS_DP%4`)VZ6=>?G9rq)>uq zL;0c37a^-Pu~<;#cF3hd9n?oosB<7Baj2ujmfusIP{+yj0W2Us)X_Eop^kC>ewBHl z&O_J;TB-Fwk>BFyyiiB+*-5A~s79l;{JLjorMBSiVJ;#+*y-xczNWTNv;+5U<5qvB z?^d`o|ISk3&Kw};aHoe-=wiHcU|jns-m#5K4#0M%;vGJYV-%)*Q0l86@hpz49U~sG z_8vz(%O(EgP~v2XG$)iek!ZUY@mwU;EwlM#iL{VS->JEd-dzTgw9|`-XIkLDFyg5T z8QezL;izX3&j7HH8}Uqr_>&_ZEALFivjddacEp3c>WD{ma*B9%hR=}^&oQZGp!_XA zY91TC0sKailphTZ=ndd;wfOtO-;Iq@UMf7b_Z`=*#7iep)H{U|JiE+~qCN~+t=Yy# zQP)E*6-A+rRTLF&HpWW4i+m@@#u1iMMZRZnA}lA@4Ol>Ygr#i`A}ll9_*LdbSl_}1 zW+SZc;^({wOYzxBgmo;v=(GXvtlltGZO}6huoG@vflGpc<~^sADknG4QayiU+rSHE z@R;aqnEiq^_m4bJe`q}}RaAfN@~PTTvo^fpvf8!=ZdJpOiGNH1$~}7d^2Li892)6j znDH=(J_0qOFyq&3Ca{gIOWVm)QkY3cE_-AMlvl`n_np9wpNMM|MlZHe$qtZBabTmD zBcc?O!Etu;vZXf+NvUvui=W4D(*9DDBl=R*JZAhH#aoKtM%ryrze}W#>_Q1 z49o&ruzyvt@4nsPPREk?*tfElFfAf&Qorg&-1#C&4mYOd;57IJLI$_Nb^z~L+_^Kb zkQ;YCFT|f5cUpO8;?AFg-)=kZL|#F9_}~{iNQyfjaCO1 z5Xf_Y)K_Bxw5afdfFSIh`uzIIcPImFe9JyCu9Cco47b~REM$Rx=>=M%E!X?zbNIUe zhiIVu7RvtwNZm&UD8`O|WFYwilx>B{LJ~*nyYRjGh@E_ZA404;3W}F=K=026m4jL^IqfJU3>6ay*^nttfW61 zj#}vyQ0VKiRv7N}dnZ2T~-K*{Ax1}=H5Wfj>10^LCOk88J1FbacAde zd302&&9pcZ-=d_Wd!tf--~5c^sJ*GCdN6w)G(sVKyKI`C7;27APVhAmJKdEJ@-blc z6h8vZy=1L5w>AMmB+O(HRco}4S1=Ke+jzVIZ+QO zQ9UG+r{8IN4^YAbL3c&tkOm2^1i!c+&?>*!YYCYPl3IIZ1ft!Wkm7rh{>Y{wR%n}+ zEXG!no-9_V13EN7RlnUFo=vkTRW{AyYE+ib@o5srGG29xM4E%EJuZ?K!5v8uy#RNf zDezRdsCcQ6!5xaX1GsY(u#gMxToU3>26wEy(=(%F4=Ay1a0hvX!HU2gWzmFW> z3&(&v$FC%Cr&>Wvt!%8p9fmb{?i6PD6}Wc*-aH+u*Q(80#eD%+ch0u*n$D2C6xr-c zuE9pcU3$0|=1`X&UTxdhd$i_;2o^b#x(@joNSIS-n1t4N!R#@P@2~Wu8W??n2j^i7 zB)tGCW2Z7C{uJ_3(g)oZXpjw=c!K&K${LYn4%W+!?*xC_Dpj znRa4Ql2wV63aZ!#m`$r9Y67`uL@QYp*vc-eqT~ef*a&7>B}-8trBpI&wSTlkbB3;-RRPsxQ;?&kR)QbhFbVNLjZit}g3#PQ5zXfGHJw*g5Oe zPhWuJ5iGJs6Clmks6KB&SNhFYYV<}mKFF!A{9~THZ-%kt1z1yG^85(i_y$EDUFSls z=S1XUp<|1pgl_B@D?m4=f+>Fno%V`6U)OPo5gj;bf7#{c^&{YbXvWiku!=kq#98Cj z%W81r5kz10+Owxe>$PEcZoW1)3^ec!R=yiBX&#*49I3)9^>o8$bbc_f`*9wvN;$;4vFYL3@KS9_j~afhMZH;B)SDt~!?&n; zpm43hwB9C^-X_P!K+K?(u`w-2g+h|x>x9suUNM9otHCAUxD$xFL1pV`b7VfG&;l9+ zbfC$h>I4McTD_oiu!QMGt!`gQ-QLw&DZW=p@z&B(+|83>akpW_N>5p!+nA}jpOO5z zfLNiMml3ObfbraIY08CkvMudI4O*z)O8e7da4Yet8=@*$Uh)^k<@VHkZv&)|2MW z`wY9Zn9Aqzpm-h^N~Afcm*Ua)6z<5Z%??p7Nh`fTy-pGMFGRf_FJy2Vu^mvaUxTi5 zQLht1{K=@7m3Id9`WjT%HtL1ELfB2Hm+D@GdVK>vt3XY7!y~n&X<#LzUV0%Bqp$`B zLh0yBM?ocW7{gCCgW$mMY61C~ImAG3{UM2IBl5JpwmDr9(Q=+|Y(>5X*k7Ixfw}~o zwX@CXSa6tj9|$TswYy2_9)mL;9+gi{=IvznR4KR1^BBPezdF!RJFnaYN(GyEC1nr+ zHI)h-SzD+sy$|ccNVuV7mp%w&Gxb&4?odu$dGIU^9t* zcF#vvokk3;LNeBhicHcjt6&S$%LBqfx$+jKmlA1k3)2Za^Xu0thABhJXo;eNw-FR= z$kSu71_i{S`NskNt+Lp5e?S>T+f_+H+x4~uXmr47Y%0L{V}L`)a(^EnbuBmf1Q5qV zM9H6l+zNv&*9aqHxh6%jT$6aPwOm1`)^v;Mz;?03(zg5EfVeWYn;&W+Deq8vNkpj( z%Anhi0%iJ=CXsdxa6avBA!>HQOl%L2O-}&Q;MnBBU;A6F5<1{@Qs_Ck=~m&nB%tdx z$WYnMORFLp%v!+)cUdbXvFGs!W;IfY!U#nUo^~?sM{ro6B#+D}hQ`tt2H5Ms&G^-3 z{LS+MHKW<`Znft`kZNp{NQ*l+uluNOSWL=bsE##DZC=uGyisXpnT!0k00n&l9E1!7 z-2u(ZgMt`NX?OF|vZ2ZG@zExLEeQ0*06^ju5MC)AKtG3j1;M@|yg7eky*e>8qK_r^ z0R8!5z|!X?`J%G45mvgagJk5s;Ay83uagkx2-bAvfC# zdAc&9%^W}eKjdqGy>~Z}CmMY#{qQah+-5m7*%)n3*0<3-e$5oDwBpF1zNzuR2b_Z5 z|BZnb+Q^Zo?blHTaoVnugechG!?nBL6m5;^&&B{LRK7jHCt4rFPVWnlx>0pm*y)2% zwiO9a-i=5ylXsIMP2Nr79%)6IrnfRl&=E18J8jD!8%&pk4G00DASuI3GejDMm-^I5 zUFp}b(wP(=5}G8Lq8`~biX;y7zYMTxWzXjL-;_Z#N0k&b$DM(HZG-f;kv_p@&`Q|VN852LyftuBeR8~V?q+<76E{4&y)oJ29wxElw}@P<2yA7PB8()k0(69GmRIbJ86wt`!cq{io=%(Ym4%4!1vUhT7(dGp@u?t~ z9znz>dkEx)Vc6U|gj2y7u=r^4l&cFl+wyW@T9z`|n0&PN%;zFgu|#$KBesWYF`8bl0xifFrpVZTDESmv=Mk;d{k&)C0Gw-sYL zWns(t;;a505(hG~Z<9z1nay|UTKEWNOBU4&F#BGC|3WbPGeU;#3}z1l3%OwSr$YS6 zV78Ta2FyMWN^Bd?k%QgYKnj5tbD9ozVYtDFww;Zcy@kgQ546zE zW*8Palro60kV+C}WL<#APYUpf#=`LUi2+h~mRA-YKLyIRB4L=wh$I6OnG^{oGKm=s z-1fLk5{w&|Pla7;Riq{%n%tltDB}l@v6| z07QOufFsBFt_+a6#+O_G#3dl|mjJnKJR6^Be8%`pie!8y(Zj;6;d!6I=#aiGqe}t; zDQ|SAn!(U6&8&x83hie&xXD8vjGD0Bs8NicJ3%5N49*uL5}GmG8EB1F58LKPDT8R6 zDydW3{LcVKj%|K9K-!6IejUoTjc405jnCMoNs(;RBp#Jfs}5zddNq1#Wpn9RC7TN@ z8*6LJvOgRUXU4Mgrv*sLxckD0QW<%|kRu9t>PvPa(yrm|2Yxm>E?Nkr!MMmp`dYJA zPfnPN`_vDsTu$suj>2+jZ?7E%qk#0q5xld2k@qeOI0|EZVg!pEcAkx5$PGJNOYyHTMY%<( z*2oqsz;1*_7s|<~t)8nG1wo|dq1vsBQ1%Tv@?Kewv%aiSFcqeSaQwY-+33_%ZCKx3 zfL9=l!`(;2aD4%i%m)&@FVNme(4*3=w*EzF>xu}u``X$SgsG(y5+?6ZqHWrnOWAj$+0-*UQfiWMz z#0v1(R1YBLcLl6PV`K<1za0&XynO4DUV!sTj)dh}bb0TrbhKZSl1z7?2=OD4twT)N zwl28?8=AtD7s@K>5~TbkiBTB={hUOagMi*cv|WOfACM}RdHk_N8q4D@+T7EKaw=hA z%YN|H{tu~onbW^Wq=lUNZqA+E>%M|`vSdxYz>^QXFB|+7;>iaK8Qex}hlBec1DWUI z$p?n`lksFL?+l*&W~i=hJQ;a~2?62B$}JF{{8sp^VvjJMT+w*4-W-kgE$xsF6B;v5 zR)Ltn%$^jG7S3hVVBb@hO)@zbS=wHEr8h)0oTKumBVPmT)H6FD{%OJBD*`RF6MRND zwonEU-B3wEbR)efngN*fXJdsl#{O%7Pc%UWgIfVo7xO3!2EP)@wjyE7!-yn)W~ zH@M?<#AY$zwN<#91Wp0L>S%h{QvtmSoc;47HlAb8V?P)fkk8rgbJ?iJ4PvZ5*ckVs z45Bfrq)v_Tr~pTfF)j{}c4CZ!P_}J68>4A_#u!bCWQ->9u&^?XdRh_0V7ORzIm3PR ztR3JK8vF;jcMnJ~W5M|`JCZWkJ08(57_h>SB7~Ii(etMgY1hEssfea?+%t|c4#hnl z*qgUYTJ7}ANwuoaApnKFAf@goZ1{N*O=W#xQ@gB>lAEmG6u~U(<$4rGDZQ8-)U$>!YPsPmT@qr6q$EI0eLi_W%}O z2I?$2sGy-fgvE~rS{2LmUSJj%-$#&-2FArS;{j-3I4!b)h>Y6?Cd;v{X=Gg1N(LF9 zZ|Ty=ZYF7A%l+iDzFuNoMt9drq&evBDx!6;^7+=nGW@2KfM4g6&+nMTgv{@VL|Vvi zzL(S{ifFW?!Cs)zErI_+H2NALgFBJi4ruflz(Ot>eRYUG8I88`P6I*75l~{=Xf*N) z!4sj;sw)!m+7F-Apedly{u=jbXTj(}vvS{mR2p!;2ZtB6$+@|8va$uPbf+({gG*oR zp*>8e#h4zFd<1##OFoP(i+fRNG3HSFk3V15qIMW{#~ z_`ixNIRk&9ScUMS?N#d~!?m$mv$g>dmY6~RP-(f^DI<5V=OCqEo%(R6nA9a*8vp6R zNc`U*-y*}%ZVpG{pRhTM478ryods&A$(c*K7I=v&D)+t_Bc~Dfeo@&{~F zdc^JNTJ&yT5F{>-SMwy&obhTl(K_R+cSVOiH{^ZJyQ1p|sbZPO!z9vJ9xVV#(=N+p zDj|O@dbw1+%<0JzX(6Y+^Ku7H-7RqRm#nE5qyIAm{tHL{rwJL{Mr?=C|4-1pa!3EC zg!q$3e=G0I=>G$#uIN@x=8ctw5r$uN!(4;QMF~^mP ziHuiEt_AUcdA%ecC4=_#$Sac&u0me6*W&XH5iMp!=sM(UfW7#mXYu)tKnpG8#|tbU zpbX*yi%JSEu%uU+8RtrWHs(iz>K6ihqV4hG^L+tQ7YZ%A`1~a(+lqvjU5rRF%PuBG zT6QssB^RGDpMoLMUZ-I3`TYT*p!|68`8`DX$Sgk3`Jxb#I3uH#J)7fBltDB{l@v6` zz~XaXfFsB74hWFChL`*Zq+DY0`7uzoZ9E&EX?(`;Op0W9Ced4EHvKJgQ5VveHn@Lu z-QXUpCm(k4*?fToXceR@FsjYf<_iM~vr+XcTHi>3Bggt`0n$#aFM+ac ze&PN-t)Om=+exEF(W0V5p-p8=~&4RMv$_SQEpvUa?~>NfnO?) zVX!r<+J!(0s(lUgd1)EB=*lfpt=k)u0W3^)y`qf9#i|UjW)Q(IFAy`MxPH4hA{Q$H zTN$MYBMGbk9if`&6?y;9(GS2xj ziPV|RX)WQUSl1A(!<`2YTmHPyd8qL_rHW-9Z<0u3d0dbd?}%kIn+A{exb(gW+$HfL zv;1+1w2qq`hRXYrUE!ai zMLrYhb?vo>lrvV#$@7q#?FAwq7SU#o2M*3qwS`c!7r?R4@xGZ6 zkK+1o2KcwiU`zZ@${<>zO6t@Se;MG&vBaMTNIS8_Uqjip@ob5v@fk}rDUv0c#QkJ7 z8kMwi2p}%OGD=(LmjeRISZ971j-(7LFN-LZffWoFqJWjYq>o6u1}h);m2e!#G0id{ z4aPJskkva_c_p#}VV}l`qG07SBAUwjz@~OtA0=VsY6P>amuI3dLb0Z&m-b=hEdjPV za3uw>ay?Khb~=WYCnHE%$tbrjD>({Qz9E7|R_%2_3aUK_`h4fG@~v1{8CaPz^d;|& z;Fn=#W)xB1cSq!6MPMtV6k#NR6`&(T9}vpPu(F;hYL`*$!g>3#o@txzm4%fz0UH9W zjGtv#`PL0kc+hAAzHr}&!ITdXcOIJ}IslZHI*c?&n`5;>*u7R8gS*%8M9FBg zHr`Ojf#}a3>_Prb!1^>=hOqK4fmRJBt+id+gY3wVP+fZnXug$<-kI-yG9eB{o&Shz z1)|Be70KVRK`AtOQCJNbSa~+(QEXZ`)cv}!#lL*M_xq|4RLBtMUJ_{z1iBm1I>_>D zGO7%N&R1Yi{qh-HBGoE0I3SV6GC0qedz#5~3cR&oX?D^I*5J{HA-FJf zW39Qh29M+7p(z?J@u9lm(V=F;Y^iQ1tLX~KyMT8v#dicGY691Ro(w%CubYsS?FEs4 zJfguI+kO=J8sNdIn-KY7G;CQ+XgvlX`X$2JM6r1{85Dk(t8vaEh4Wi+XqoBi@;5iul;^j)yjasD&_vynOOP9eTG@IbQ zVz^vss#+gyz)4QgF2m8xk^d=#Th2ggRl|0ifYhQ7jQ2^)P0ef=t-9B1h@=CIA4sgXyVfdw8tuyEqanNh!(Aqf)+gs zTd4wH*e*jqe4bts;K{M+s{*8**z~nfwrxJ!G`I1vop#t^-~}_!o#`K$oxJEnU`Pt? z*|C4dZ_AAV2A#IViVy9>h>w2wRlYC2%3A}Zorv$YNb$A6J80<*q@;ImfWM6Nz%Db+ z##pT6Y)s-~qdJ?BbSsV?+zi%G+RcnbG`!qEd77C=cF)b2BDDf@C#!!5w8!={b~6uC z2GPx^q|V*Ug0B@1=8kdg5+LoQpX>%@+vc;I;WkFQnZpANI&Fy+U&zfIA7AA$0n$#y zcVevg?!$h_UOMe(&JQq{5ufB|jLAxV#w5o1jW+xY)==8dJQV1c*l^F!6o>h|9{ah7 zFrQZ>aBdn}SK!+sKdfd1_h+v7>rZ~>d~3~BP=t!{K~d(n5h_JKS4ZfaC(u^{X>bDV zt@|z3qX}XmZs-QV-ZF5T6`UQ9)(nr)^rj81=qxY>y%rl#b`^IfLO`rV6i}D7SaKEj zgAvTKHg7{=gy0ZQoAWV9RdG3ubp68M1BNEWviAk}>cI7JeVMW2Kd4IdQ0ZV)rQ|R# zM3O)3CG%8Y0rP1et(Y(NKfE;k=>Xs8)!1^;7)n`gF$25=s*%7_OQ0HVHMW^u0^JGR zwXg(=pXDXcgT4+aIX5tMc(Uf$P4J@A27ZC2S=}774tlt>4w@<_cQLeeQFqo1GxgB| zUcu!~$E9+lj_v3(xq}EWjgK}rj1Ko;o%LAIWYIQoy)J|6tV@7ax%=MA%r3U>krI)f z5M;ia@r%abGa?&>%dWOj$?4d>)UxYg{vjSgDav&_i<-{49lPl2e3TFKTrBY{ue+_2 zNFBIP>kJR`tR`BAJMYwv<l-BwWM;3ENDGX32Fil-Tx?EAk3q2raoPcScKyN5N zz~~GAR-2XaYIA4=UlE3n)`)r58%=MFK6wz?ft#(7*|-ZR2QY^^G4wOrmhU?AGjRMc z3-1r_tDV2LS_hoF30H0E;l%x9xTKNfZxJkV{QqaH? zQ0YH+w7GO$ZECVH+MKL!BOrgx6fA+`0HwaEk;q>a4URhpe4|(iHk4)vZC}a&^MIWy z>4|_!5+(wPi#WB~Ix(~)z^8+y92FpSCr4#hN|!;|RwN9o8Ifc_Vv{0)Hzu*#Btp9zq5 zVuANT*|za)fu`{p3p6Q`1)4#W;etl9uGPmLRlHq|0z0E1GOafS`0BvRMtZc)6#WOg$Nrjsh46D;y|$@Yt#7V1XSlu`{)?RpPcdE>;12sOTPP~Ml!X>E zz-uHL9x&zvlOz8}Sko|J9OH@P1~2L9s*5klqzeGEtJ4!N{s z((+iTz2Vl;v9Ze7lmYu2*@Y9ynPlZ@*6yGa3 zZ83F0Fxak?W!w9ZYVWT~w|6hEy~T#ZM+G%T28Lr60{o0LT@%*H&V&I~UMHLTEl9~( zC$p}!VQ9JRa9Rs;vh>s6gB5D| zU}dcF|FQQaV0IN%{y;X803nbCXdsWUq#HU(r<0Hc5JOl**$feafXVCb*XeiZ^lRUH zO^C{<ftojN*bD%E(_Gl~qw3oY8RsSzKn^6%|na=Tx2A?mhQb-M2Ku zeB(Dm`rSHp@7e0qso$wvx88yJ*x_KoER0ft=vW^+1Zd^7-sr5BOo43wxKh+WOg89I zB__e8fpTGq%*Yk>qKL5)+1!L3D$n4B9BC+nQ^39B?3rr|8scx4wHo(4p0x@`n#r0Q8Ew2#jR-6& zah}tOveMfa{xi!;*E1b#AtvE7D9eF`)UwjGKK}T!lF@gftTYeq*mPM5d4a2W$$NLguxC@bMdQ1DF}QBlG?ON^;PS-#MblC zD+7b}MEMguQA7?EFoc+_N6NXHFeY~9KEY#uV-)hpHKGISk+P{(k37%A5o(b<@@x;O z?UB(!AkI-`+63fAc=AXse8MAj3+Iu#u`A1f#xpa?z(etVO?l`lkHYeM=yJ%&JON@!#dfy3gxnsV6JdX$xL*z}AX zNeTOZC?HT1Jcmg}AUt=UjOp!qh2oI_(J2#p2-WM$gdE^_>FMPv3|t(Za&YQYRE*N~ zB2K|EN3t@YMnKM9#yfI$1dsV0<1s076%Uau0Q)C8_xmKd^X-k zSl2dT+N%}fZ2@g95zv-+IBOwFHKvN^CF0bP;*k)xx%z-?WCAzRGxdR!+Q)xreL%99 z9e}7lQ1Ebvv5K4&?Vig?vl*cJfLhaOk4n@BHoT-(66N};JbR{CsExy^w8P~=@p=^; z`cSRx0Qg_blwyA*V&*jgnnRhOTwAZAMjP&=eKRV9Iv_l34^SXs|Fk~b2YM-~@6%?w(L?RQ82yXd#B`kA~)YyvqvGGxzaww9GgHk%0Wjdq z8ku!FisYZESuBJZfUjBH1dONFEcCLl>6*oH!g9DjFyzgi!%~YCa);scbLzW`5Hm(D z0OkGaLn_y5oZH4Kg?y5)JTcG6g&jIokNBj=trYr-^@xw5CyH$bozjOXM9kFUt59KG z(St)wu>Tq;0+t?(2+@~Nnpo*!rdG9hYPW^xPnBlFH?s|(Z(W4RQ&70PeTU$HVzX-w8PXpW$&$!}-W72F)vB-jKse!1=epWsDagaQ@oU z)mtJW*Vc#(zww)5crc>yfaa_4O1t0y8(+X(JUyJ$r99JG=b+V@7x%RG{q#SURq+eHT!qmoU` zQYRO%{~8ZR=ne#O!oJ*Y{7^^1bk3+o>r4x0K-BlAp`pY`x=OhbP8Dba!TOWEZ0OBW`k+Jk#h z+e&0YU-$56dFs6$QrlCbw*zqw!2cUSZqz}Zs@0M3RNcaPs%|WB*r{Vvt&4`A7Q7hm z+>{sJ>QP<7i_?=KBqb#EWdV03AOjryU1L zJth@N#RMP$p@xzhw+QV4&T%wyFP1tqaYBd-0!+8fvo{bAqND1DGXqJ|7k0 z%OV_ewgj4P@o?5ccuE6JH;YH6fTpsMiP$Ni=~(;t4+Tvni`lV;K+_j{xWi#gPKtKV z<)qmR5NN7$W$jT3(Dc;J0DQvh6NP93sw>69&T4Udyi^qj-5&o_Pzz#rUqP3Z*j-1JWe_}hrjF5#8jOkSdR&Pd z_CErJLNw0^75zKP7en(7Nw-E4-a}f+qCwE6nu`GMi61Vrzu=hVF|?m?q$wEMy4>&u+37atOjrBJ*4)^FE508 zAKcq0gMcZmj07;HTR31!Hy)BZNNp#LehBR6Ku-^Wdm9yylWG+toK&}PPO2N{;XAnr3u^fr zd^3)4995^E z=+9va@JeecP@l+VtRRAz0saalnwE$XEPCR@B%e_H2+R_y;Rwsx}1GKB)a29nW`cSD} zERP0#9{Lz=^JMZ?sW7cv2#;hOVcwIxTemtiMI8>(DKzy-kFzM?1<}+e(7z;_x}`lk zLz9BlJi^Hn(S&PUl%f>7vnT%Wp z2%K(T2F#Lvy4)_}xaDEME{@b%O(?+-FIy;REgtuEoQgy+yzZ@5S(?b?)`EsViB*T`o zfrV7qa?Hmc4_g|2Ct%B8L(pp)wnSbb{S~mK3@QS){4E925ZLlKD<7p z8#OYV=sYr4A3dg{n}J(!zQ6bA5c7GN|1~-}4G2xW3t38oPTPG<`6mMeC+zg&$X5?d z6z%+K^J-~Ic?9Z4@yQa6MNt#1IbcqNGOI{o#CudShR0ATNv?u8Kjqx-5!tMEX{mp& z=)f-ZWs`TQKMRjwmy#*o>`U4m#RUGShd=a1f>0m!klG9Xyb$W+aBrguTKH>KBo_X< zgH>}h^58tlnE|1EPl+dcL2vRSMdaTMF z3f*u7pzz#t$8pJ5995z!3eIOura=gmxuCTn{Nk{OvJ*RFEb`lfMF-YzWs}!$r+`4p zVa4ArNBtg-EKgnTA+Ig+V?Lg8GOY9_@N}|B3+7X(pOL)%s>4XN%%Nr_#(J z(+I?`+^Hg+z%qCGO}e71W9H7r!$mFuwbcNb$uKB$n+-EtrCGbi^{K_qH7&Y`KOYQW zmJIYhAkAl>edX*(8Wu5!iB1s9VuUV>|Kee>g(wq$a3bK`=6N=bM>6}T0!Yd1sL3{) zeR{Q6u9+`=PTwSdx|)0>fJHL)LqH0~z6HVo6#s!+=S;E2(bBS;%R5RJ6h}|1R^fC7 z_`fr@10-C!Vz4BpN?8tfPTP%si}#hNN8mlQ2(oWi^!orQ2-YR`XF}xubwDpN56T{7 z9<3jI07g!k;b(_$0`S#>AlJtm)p|=0!z5UV(<}p4;$o9 zD1MRtaQGvZku_$h56;4;mqu!hH3)gBG-)fIldv`L6OKJ;SY_gFsc>cE;`Tv%%u{`P zOAp~?2l+d&m2?f*FzXEm1>Yd}xe{n)3NslRGWh3wRv{`8O=;DGUrbh~2a1U(s1Y+d z4JD3kE}a5~kk7tFId{WcGZ><|25(_wAD5#`IF5Maa0^FjEoYRC5b4|;NQ)2~Cuk=i zwpTGcWxj>Ii|Jsm-zH&a;0u6-REX_zAAdZ=X7n9jphipKj!i>s$Sb510%DUMD}bXu zxGblY=*~U&*h4w1jKtl}=u(iMFW z84Y=zswY~GJ>=fO_u-$D1%TZiz#=6&w;^Ae(|DpI)$D4y4|Hh0aE90iUH~wwbVaoY z$B5xNL~9?_F5*n=+f$yn@(qswCQ&6=;6BlTg#~02lX$y(0zK!WKIY*FGhqU-e&ivw z6ZX6S){o)dMtFh+wD1X7K(}zPfNnf8#E5zvG=j)spy2)GOiKeHk*(R`&{|5|?NK0- zQm%^b8zcJrW~=y0FFZ*zU*)jJqb=6jv_Y1;}Y>=n|LC45O=_yY-GYE(lZC_y`p{W zhrTN+SoE>nKXC#bhu3Qg z#bNj?ubfYDPudds)tTk$n={L+TefUjqE-;C-bN3W=mVe#P~H0iR425o2g=^q3mjDD zIoax=?MEuT1NG=-irZ1RJhP(5k-)F$?*PVAw;#!r42;n9_M;`+(EuTDg&xeV;<0!7 zs{KW6TD8lk_*Ut&r7XAwvIEQV2R$C7mVCG@|0X(}+>_J+6_{oCG$FAXH1tdRzL+Q; z4P+aa*@o@t5tJad%(h;BG3#vWqFHEL7x|YppX9jWm)cKoq$x}7-vrX)QkxUD6HDzw z9!aKFnM>`3Ob0u+oP?$JN-$C!d6mz-99qcKl zN=`7+(|B=vW?4(n#D3S=PNOXOIM=jmi%I7Vfr8+qV+4s_k21w3oqcSbOYp_oG&&Vq z<#@DaA9E3AAMwLw@0}cb{Ot309BInz^EN?iaW`FhN}NCEGHkmgDwoGka1Z8r{3u77 z$)h{`?a4*C7|xKKWjZlKev9EhbB6o|)4>*E5@yJ&fQ8f<@@qc+_!-jZJ26A9!1kcH#Ixz1bbLA2W0qdgu4 zHoBs}cywl_!p_7yp^~SJN;-dT=z$=(4|*pEXMfaD55>ns0UtsxMC9lx014t1g+2C) zUvpC*F{8>;%sFWLgc;lOJ2 zHXt{`ljCXO6ON}_ILFhCvu%@ULo}Sr;BZKv+uxY;)H`c9n=t1|o5A#s`F?BzCf{f*%eRAxe}a4nG)%^n>{Tma z-H!#xNyb1q+iVP{^5U+*uv9&1DDJb`-!bRXm7M-1vB2Krb=`N*QDbtqFVphC{jP z$d1WWaZ(w1uAP-?WuwPgqE;_vNCxrR0^IS4*Q-I=G{lQgq-J+kE-%;A8{n|{Bn0m| zg2TItN)|)F=HV)=mnLIn0ht6_Sd+CF%YlS_j$@NYnLf>t zrl3r>3R;W1nc9Ekip;PWZ&}c=uDCjVfa8E?_UjyJD6?iemtoUfW4Dg}jC&r>+T$E) zCTr<|QVj}3>o_m!1X?%i@no)(iPp_vI!rQJ_W{s(Dq1(y#~+W@8GXlB%25Lz*ECv( zyh3Iq>RB=z2x#ifa9PfqOg$@x*7a{3DGgpGKL7(euZ9anv8!>s0{ePkM@9vH>(3s_ zfvI28Zlp+?#1>2}v z6^%3sdU$Ss{jf(@`Tg~{nL{k?(ySf&Sa-R#vJ66PYan?pOj5rpY$Nl^F16{ zzIcF#v=v`m2=_L^Q;^icCtOgsa4x7D_eU3`*EpobjPoVi!0oVSZnyhWUbjn6<5Ag! zL2n7TE8#DgMg-w6UD2t6v~3vl#U779c_`P}0;Jwt$HAaiZ>~;=q!r7}XhoB@;uRTM zdJCr)M*%;pz@_R=K+;s`ZL+scUNnlL=7qV-0jeZ>qbl2M@0>9AH37_$-LFDr z_;Osw?o$UUl~G|vCbmH&lStQ5`J`DAVj$ z-_O;J3fl3@?jV0MP$GmCM7;9M2Fc)0Kc5{#CIX#La4drwyx_q2V>muk;P`KPZpL-`Lw&{0P$29NkDlXzJ(tT6=n=3$}(>zlI4>zf{s?RXDI zmKUz{klJ1t{TWoA1Mpo7_cp?l7i!@XUZ`6*FVu|(FxJ!dXmG7CD`4;3zIcd7HBI;; zrkk=9u^Ik~)goZ`qfS_3zUWO_$2`0mGmsBPq66!LvdQa%dtNv8;EUKdw=Zt@C?>xz zu8=uc#?jg!5Yb5NlM9k+c|svl{nR=T4sg4Nd1DoF&d-PrtaHjHuXEbFQi(VFlFQ#W zJp5S>`ZW(}D-QYq+}o&v98{|!;h?&Ob5PxQh~uEHJ+&4ZSybS%c(>dx`$>7Qn>qqpJnF*C^%)~2LdT% z;~$5|a~pO~R3!;L=g~*CRGrhixN^7j9)pjQn+RLGwH7!Mx9p0#17xO6za;Ez@T;Q& zdXX_vQ$fbm+QbK-UD0vj5UwjG#|?9nF;`5_f8$GO;LevrZpq@P3cCDIgPz5jO*^oZK20wx<}85I3>0doDvF z<1*8tgRPidJ{c$)RwayR(I-&KSXH7EM;zS4vBx9RU*$-xb+a-Oo@M(bL2FeZ)SH%K zIx|%g=W^N+2S4H-%=7pIjx>|U^ejfngXlSDnNFbRd;M237s*7=pYaGh3F!H!frV7` z{AnM5JbG^Qoj}ju1$S&3Jx5+)mJ{f?9AX0feK%aDyu*v0ucGsIVQ+M$S}zUh@4_RB zE`oTWB0r@n1G_i@L9Mx)>#QS6v>f~c+;J)6CU(t4PvkwFjFCch$0A3Q1)QG}AU7p( zCnH}y6i1&s!1<*f3C)6&*4`J14(!@nHhI_H@mjX8mH>?aeFc&y6UJbi&jDX2dJ&d(R5Uf{eVM%C3CGhdoa5<6 z=gb2=-V#S4AboC!d!I)c35QEhjF6Pzo$~_jO3OqH$iB7TL$JLZrneIXsUHH+hg4I@ z(!aItM68F$%VIkazL84Ay&C*0UoF0Z|)0Y-2DYw?$8A zv)cxp`0zIYERwUn2}r?NPk;c&0mxYgH(-o&;o*1U%_Izw)ls`aBsz3OHwExZ;4d+X z2Qu6c(2ER#QU)19YXTpDQD3ekvK@l}LbdQvK`^@$opGubdOBbv0m7?*4F({@%RE4M z7f9PtfKXNs+5r&ScWN0Rv~T8|{?LKl%0KWppTcSoAp9=S%Gt54i(gyZ6oAkru>nG- zMGr_3mwz588UlnywCKN4N**AT50m9z3xczDBpU$Ey2x)+p7L`hdE&vhX96Wbfbc0n zYjLN(@GJtF;m^4Y03pfds<11Z$Auhe3P31%Ophzd=@1~~EYk^q@C1hcOn`7L)4@)D zCjlV*CD=L@AYAR^j|T{izT=DT=s|c~(*Pmz3MqvE2;~qHDA&KkWjQzbPgPhN1P~Tu zr>5oXr3XMX0ty5N9QNoD^CUT`cQPspWep-nlLZOBGC*!hzOF#NdMI)}cOb#P^+;&) zZo**RDmt(jjBH}o3~ks;`ymgX=z#r-0lDPfnSu)vWs0?2+;Fzp=*zk28wpxfZX|Um|#UnY`P_{5}7Kj+xzFci&I|jjqYH^YaHdM<$9Waux;TM1n1~$aYJZ!k< zFFOVsE)(0;WbzlZrLd5?rI2pY0$8}zVMe}KFL%cDitRG;w1d&|j&l8^z79Z#3qj9W zpU+Sz4nl_q0eXg|1P)95ntiY|I3BoZrjt`2Eroz?jX^D#qVSjv#x9dw7kN@Cq^WK zmX~=*?X`AZXn7^v+o*(4J*|=is;65xR8KeNgqE?N4dSFvAgB~t4bS%|1xX27K0uIq zq2-S3HjO-N8r_pS4vP+~JIW@nJ9^;cS9>_J9Pd>gQrq#O(}6e#ocvlKH^P(SY2g!& zr&~D3(~W_BAue=f*pJUkl%koSE;bYQ(tHnr+~_jx$7yzg!gX)E6M zb-1??p1e;BpYT52!g-%=lTT{l6F#Y1IG@ywM}`n-g$XLSr$d4MJmKGnXK3Tj6c1$8XTZDDS=mRqM;Uohr^j8}ti%w165a z)r;j(y;DD(z*s(=2FyJkGk3t6sVmwMATt>TWp1-!a+cZN9Kb9Y=x&O`kwV&;v6tM>< zLa7laUWAh^+0llU9q;l8fCHJF8vUfrP90Q)do+MWa^;7C6kPd9TcI z#d>Kg)>}eO9bdxL;+T7-mgE{2wWoB&K2ubYb}39<0$bf9f2A%o4rY3Fj~DAB9jNTB z1>vKakOe%B|TponnYw`;0&VvD{|_j7~>cW97c7Xao7^ zTePvPi>Ab5U4%CRL^qeKOF6Fi0?$PpX-X05C4sb958;IEL_Oq6hNsNk_OD<%OmaQs zOkg3k9)oZ-ftx8 zeBI(-0$8M+=CjCGkKz;rzA8slE8f zTY>lq+}o&tU=OW=1ni+(IM_os9+YZ9t%F874U7rAlbl@1lM3xRV&LH?mz@%M|mRKW=z61gEjh* z39-%BSR)97SRNoKSpx-avo&&J5a$IjOIA4>6_P8+#m~MGQGlYCsZ~w5NFaY1%Du7x=h%4+YkB$}w;LChsJv>yPvvILq z=L}dw!E@B;v(s?88qQ72W}S(fTQIRJ6i1=^&@P$o)e6vA-51wd(4jas1e92Nfgk0u zS{=yYwzI@zF+bG#pxzwwTwqlPmgo!8kM0QY2-lBrx3sdG&q3(C1eJ+{nf0pD^$!uY z7|aEu8IQUA2QZ$7xtJNNY22l69Q*_vZ>xm&Lm(ISLvQYFQqdMdi83IOquo0>XQ}oU z1}4g*LnU<-&B*KZ;(Q*51F6)2Z`3{_CZAt;9K?o4euh3Ja)x$&X2%seabUuJ@pg%Y z#xJ`P{W(w~#6yfk(bFhg3=f$vSBYvPI$1%exAjlE9r!yYW8@K%IUH#ULNZ&>wrSJz zaomG>9+z;Wp*+s8RXbu}Cigmg3tQ2-Cf~?Cn`iT6jx>`^H^N2+ZWH`p;kgte}n8uxjPR@y*EH; z%HH3DeDzS!e(s#oaEC`ivpgf<>T{w43tY)2FK`uK0n%zDep!2<$O^vY;S=4DfUIwL zNbS{YULfm1xVKRW0a;ol2_Q?ia6p!B%(;~o`^lsy9%wR7Y50ssDX2f%O8ZGc`s{3_ z-RJjA3Sv!$M)%~7dy5XNJIW@nJ9@U#9^v80a=gPmq_*QlKLIU=!zR&@aBm|#Ii40i z;dr`*b3EM`xRn;^b35ELk23N*Tpy)cg>L*D*eSFCDJ)$omdnMlL3o8^xL~!(v^a7$ zFY0`aqK^LUhMS8#+#6GnAHGC%VEs@wdHry9oO8IDbIs*&%)_DOmzQ}+Tk*?rxVKRT z`K4Ay!Y_3T=a;&1A>tpLLA44RsU(o9;C*uY>n4wq68@T=g(E3#T>N-I*d_c669^x? zL6w4=WQ6v9Ye*j~tejmQ@l}g$*!pCE=#=Gr998Sfa-723{$jND7S1nk?=5U94a*G` z;M>UtW8GvMnDr|$vj!Chz7!xE831K#vjK7z2ObGvmJIO_DkGO6rqw6LM`baYiA7)# zBG6V4dDkC3EVU3j)B_XY<9D8C;`pLU+^+*j$-JnsHk&u70Q#VNCLNvAmf4{<+ft4K z*PUx_6#wf$K@fp9f<&)HnPLd^kuCzwnxaj3^gB4Nc@T9sM{2Dbm8I|yj_U<&oABt5 zaS!Hs{4hrv%46)T4FgEW8qyEpxQlx{&*_&r(ojxk%L0}dljI17TXh~IO-$;i>#YxQ zkLNl4o*)f7isKi|ZPSn9kau>E;+TqYMh!Rl!{z*G?h$k22T}MBwM8`ejwuQmUSiLk>uOWV7AI3r383yT84zW2^yx^p_AhdWFJ$j-S zf`Y+8U*OTRPW^kL%TQQZ6F3b!PgYIfk^mMdpT7wC(wsul%WYGADskdQw-ZFu-ZXQ7(F)gDrN8Jo8z@MgHTQ3*j{S|texOt)|lm~PBj6Tp5l`=oJ^Sh?8I zRF5Kf>(iqcB&E8*4ngYm&5j(g@f8o7M*rlJUlbi!my}Ijm-N&HzU$%0a=w4}klM}{ z-3-Jz>H^;baw9xBpB6she7c2mKHV5t7eM-^obC>fLh?J^Vzmx2hlcAbVvm1uhzo_m z$@2k!OeQq;h%zQ1|JzS=VEs=vwd#LMJRDj6ca(>;760pjdmG`&|FrN4|I;m;|LMm4 z6SmWVzmaT%v;liI<%zRBs>$z(N6F=n@xyb+>*dN=ag?wMae_VPi)t;Dxis49;n$dg z{P1GYf%QY#)T$rWJseqn_;L?vD}H!6+}j9GeyD{{_@Qp${7^T}V{K=Ak#7fo#5*+Q zk6Sz{O88^?x(`XI3Ka#!TLNb>WeoynyP^vOY1`gc`CNeLlvjTS)$7ZvohsB)>l*~+ zpUy0VL#ujY2wofqit0{$JIuUWG)v~9 zx`&$AI{OeEm!hks?XC*2f@`}upjxFXpK7UgtFTW{tu9-+qgX7hncD5mU_-ukdowVe zR=YJgOVh9X^jk%|t%$XTy!3OFr-&b zf`X;nPokT`ARg&ybXGm4e!G8M8)|4K8}x7z)BK%*a$zOc$Q6ARMT}K)XBh*?^{7=6 zwJ>5+yt6LyA6@-E#~fd{`wmB%Qeu2i(AwOg(@2e3+?k8Oo%rFZ?)TgydG3DAk!Et| zh8i0hQl5tOH_jrRsK3pBGMNl!*53|bI@m%?!aF&4gU(ayZ*zS7@%1;O??nCWBk;JU z>u<;_q)wv#CWn@&zkM7o%WS}3e_LzS->Su(ss^XtBpw*83|Oxd5A4$K7pq9o{0;Q5 zh)w~uf?Gb{qg~7rX@dS3iYTjYCt>Hws=93sV388p7b9Oi5pfDh-E*VrR`Ez^)?Wne zT_!rP(4K5!){bqcy1m}RCprsN-CpYZ4pj*26R3{oL+D_yig7c0zEOtPc_mF;6&Vv`FRhU zM*rlJpA{Wgmy}Ijm-JNK9`JBvIp6&rQrr2W8-O@R)$QMa+z3z3r-e^ApKjrtPdCm@ z8cj#)2Gaj#C*gqU`3;g1&O8usS6XgkkoK+Y=xv8{1ZmrF=7XL}=0SrPc_R8J0gx{VASJ`1uG(zaAOP}p z0W6X^UjwA+=6u!w$iG9jx}vuS2;%0*cy7&G0(y~!Q2ZbZX^+PTU~rU4cy@#)08-`b zTF(gpa${-xvchKk4g{P(gb{4hX&X*G`!xB9uHkBB2f>hfJyHM|axp=Zl6J9LqO|2+ zIyOe1k(T&WfKFXY;QJ#=a-WI`PE<=dP?W|_Tn&qyfq@fm0E_T&;{CvQDx4^nD`1YM z;lxz}Q-V`0;W*2!aGccE@=yq%cuXpw=-etDQryx;NHO+EAE>yV5m};I>VzD+q5N8_ zwKKf~kmKVXzf?dFLXJN|SC)`tr`2ab#{-huQX`dX(gRNbkG~I;4uMA_UGzH?GzL5# z6J{d8TkEG9&3>B6_juTE21l9#`%MwF7AQI0{${IzC7sJ@pK?8tdoa)AB91haM|ed@ zLm>5dIbSEKaF3Xq|8)}iaCiE$mpm#m;oDKtul=+LXLIAc6L9wRoF1~i?|LoM!4`ND z;Osv@;7f(GukrE6!`VjP2{`+E@VKVoY~&S|6#~wd0b9V?Kg8HA0p2^AmlT|pRre;$ z7xA!5ahf)5g2Y2D%kW-Fc}N~s3WsK@87I7hjyuukL2cl6w|lgwS4ch44^RXNSKo%6 zCkw8=KY&GA_S}bjX-;7Y@Z5l_f98?UtZNAyd|Y&3u|e6ytjXH|S3l$76P<Zd)V z_F6wLT)pR?8N^VlB!L*}77j7gjXB|J>?e~>8W*8(^&=j|pbiPHen^md;p&dOB(fHC zob`=^giEdx9axu?OB!cu!Io%46Lh?Huyfvq@UsEdCBxfv4iRJe%`Bz1pRG9YYJJ<9yC6-HX@NjR; zLE-VWq66!TvZ+;HywSsv<%@skA#KGM-v#$J!jms*;S;{7TR30TjR$f@)COs=&5%f7 z|E7HNuRIFM@0*={ZR7zDzs4Zsjb9fXSZ|a~t$O2+Jsery_^5}p6>t10+}j9G-l&C7 zc%yFNyiqsuuZ0+Q_1qzI>&i8W5e`RYjssd0f2YH*0> zA;+@hCs#6%u?3a#Y!JID&qe2nO+v zeKF+a9tK;8KlP`v3@jhLeC-y4I zO&w%kJuzK^#0($>$PS-WosB%4V`QQ+h;H5HF&I>xy(@r48hKv<()5w{tW{^fhir94 z-whCiYJvm_;oBSE4(LS|Lh*wvq=OSa0OvZ4-@cwyomCK()^nmd+u1iaXj#+Qhv?`O zJuPkbWPlZ1+u`dWN>@JBQax8;nV?!-l5$6}SX49h+9+)N>!?^pI80 zeSqm;3p@$++!KL?)OzmyKK}T6uF-d*o_hq`vFUm)@(Qa9QO}hDThw!pg3B@+4SGF^ zsppFQfB5A?^R+^#`LcKjyq?tL4fH$}?X}0AnB4CH|71Nq5}&d%O(cFXhXgCR1cr%EL88^;32hP zoxJtl)8XDmB?K&Ml_X#V-NFIOx-nx;6fRbTv}ha<}uzvm%s#TOrjdmG`&7q##S zU(_v}FX~3NpsVwS)Os)WZ^}3S)uW*NzS-G&@4`K^GbUpY^2P&22i6;9Q>)(C>*2`q z#vTu8E8e&a?rnr8Z`8skyivDs-l!Y-daiLtz8w-ps3`c+08+9rDy_{H4k`+MKY&HD>vw@P-LB7CQSjHuR#)`P06|>b0Bd&t70`<; zgyIKTNV`5h00SaMeP2&13Mw2!>-m3oQE={F!gh1upM01P76p~Ae5$3QpaR4|wYsk1 z&Xi*1#S{fE0vqy0!5&~dwJ4~U;Y}9>;hSG#59?5QcsQgQnDWgpeUH>KphP4`cJ;h= z_m#W5N2Wn^g;3l*@>l9Y1HJ^MZ_`~F9oi~?_ZG%VJL&HZROL?gIEKQ$u_|{0`jXf_ z)xK|XX_0r!GMFjHse%idM!n_YTytlta{>jy0-O;fIvZt*72p=|+Nam$ZqXK-W#}Y> zrdpI}TF|gBxvURytn(F^Z5(Mzt>_X#Yn9+;8Ba>^8*c)BtxGPyui}{C`MrW8&E(e& z7iX0v)?cmYf_~@?a zPGl@(b7)UzVxdsOmyH@aUvv3hfW(xieh2yL5wY{_2gB5j|AR6SD6Cz@msKXT7U0!J zoF&Bfm~aCzG$~W7|?^k8EPrT5eHB zExU*}_0#2RpDBK4q$12r52?Li%Ugum5AJPLKxmIvK?3d3EgagT8xPAisa8b8LkMFQ z?c#s+?T)Nwi!qy7%S00-qDHUgaE=aw_nN?=uO!zJ|jBqp*bUrYBcOO1S0E0!9R_*l{B8Ee;=&xaGIy;CYyN^Zjw_T4RPh z$hD?CUjNqG6ruV(0ix4vbrY&q&Q|G@l!IG#ZzznGYjvDmaPfcIm<;crrD%lr0r&WL%sqnO&yNJ?hzyB3YO^78!k_mCFiQr#50#P2ptI1N z-Dt+lw^gPhS?q<0M?HMC5R@A7d5N&}ka#3S=ES=yvV{rEKs*)2i!uLXCz%(|%V54I z#*Ab>I|LD|`+X1J7_G>2(HU}iZZ-pi5~|EQ*Z1z#szv)|VuOg7wHW;C2oQqDzgA66 z$G-?ux=;ZU5>pyE6al8gA>oN7J&hR@!geF@RBNn|S@Tx)0gMp*>q!1|GlAl$`=nxE zjhD3RXtUV!eEZ<%$0fzL(>nmBy$FnzwP;ib27+m404;%O9aW0~)aJyrpeC=xbv;Lk znf9fDLLsnbgo-Xg`C`D@RC7?4LD8&>20ybdLSz%&T&~7Bu6PV;lp{^Sphf~|5rg7{ z?F0sOJ;PHb26Zjd!Cw7L0tR&nu#k#DUE|}A$DoY9=+ftdx|44hAUNljFTF0fz;aJqt7ENa8MI68iYwj8?gr+)MVsv zlHA@+rSZ|?AY`<)aq*8xY?mxuB6cGe$Hz-!L$$(^Whl=Q#d^L@MuK~#1b63_U<$~6 zo0cGZ?xr%7G8|09ItaNP1@OU4!wg2l4#~(kr z8hs}w*I&a}YkG1;Ue)9(Jz7kzzoqdD6$9^Ch&>zOpxt^Y{$`9k0iR8Ts`Rbwglvea{ zQjI=q;wVTMrm%ErVS{Bmea@DF%MZP+Pq9p^)EZzDco;adCz7Oq=3EL=Apl3`6f$QoHxF!=Cpxl!djTm-Y*4}udcCEbyQl7d-#iv~RsMQr_epj^22HgZKDLlI-( zwaP!y0%>b+)0SL&n>Mrd7S~*k@8me<*WUlik*2J@|6d?2uDv-$bYkuOV}_^9wfCb; z2Rm|20r}Kh9+y>y(B>F$7Du&6!HaM zD?{_8Znm_ul}4{MX_ynb&w~JlM|0!X$Rq)lD~iH|vE7r&n3oy5PV@+4vQS!cuN58G zHMeYH@@RL>?Kwf<#U73@*P#{nIUZ6w4bQvcJ|FIFgr^m^7Cy1!)-BwMTQ@FDGo&6{ zjZ_jCaCjd%jmM)-eB*$%7Fg|35|UDaitZYepms$^2-3E#wHpCU(wMp$Nb`-U4|U0``0z5n;+wwr@0j-QxomlWmy=5)~Tuy z#A2_=@RYgOdl}PVk{5eRfrZq?-o-xt_{E;lcRcNi4um^4z1TxuVImQWJ?YJ2F*6@7 z(_-dMSVpMb8ZcI1Jas$ZX5-lGLMx880z{+o*mhlM&C^A@e)MK!sw-+B%R&2@Iv96^ zmaaBh>U^p7<^ZuNF?u)h)kD!KsMLC_i8W@$hp$*|61a9@^SNiAMMmTne0HcJoZG&n zO(pIGkc z7H+wx8yBQlQQM@EMgc<&?_w`EvU5Qy{Cw1-B5SdSjvAPZzEhC4ZLv3fray?#Xqp0~ z`9@Ql7JCcv!Fd;Z^8y5;r2q=nX6?^bJ6d;*)2EFA`LVBQw-cdYbpW$ug?>~rtBdeJp^vqj>X>To`+hCy^R5+WMNcVn=KqvSbcc_i)7a^AO*YL2zq4T$;Qmh zkUpf9RbPvJWrA@N?`y(K2=ZdQ174c@#*3uR5QeCZuCANE`7M9p>fT?>g zaiO;$zck;gH|=*|x&39258BJ^F95BaE!vm%x^gGZ+JP<1aSFZMjy32(DdPUO0_DQx zwvj7(07Z-~w->lyCc%n~eqE^BI>lxx(#Zw6S#?_%;e8=N;WGMDj!}N4{TN4@veJH7 z&|2J0m(CRD&$$d6fr!fGanD&yD#P>m=T>;!+tKZa(PFG&0eqrIS;6J>;BZdobEKKt zOb?=Jlpt=wc~d8Fi**eDnYhLAOovIvEgl5#NX0Ey`uO8<3#0D@ZgD$2u4&u?c~!WD z3=3jK{&~18=Tv`@x{vbG&DDugp$umM!E#qQZb42zh02(?Y>&tVz8+__KM?GE?gyM??U$(<@&Ns zFeTK=^-6V@I3?&@cy|p-+v*wzba*F>-5v?e`d;lH7adq|<9gBL1vmC{MUivJf=2wZ z_CYZN|C5JLbU?MI+(T-whw?%mAA)-um8d=C;(?%&1mqz#0xcZmp&N64paJ{I#3>%4 zGAi2FdX$3tqw{~R5v1Ppf4XFlG4R_d)#BLTNWo+?(M-#=buvH;AU-$vk%vvAdveDg zhz_hf$|kQndbU>l!NZZ|c)#k}{ z6CGIRlTEEU->DvsEa%(cA#KI^PKSFN;mP^5@CoPBEu8b|#<@x3X>&A~M#w_2Z*E8I z_9!Odi0O$rlG5o>R|U8?p)Hsh1feZmQB9Dx4K%(cKy*r9u0qxN(idmf-5CLS=nGEU zaH@LcO->iRh0}|pH8|Z6ve)X)a;>CmY;C)r@uIff5`6ESG2aV%Yv>&T1|Tm%1GL#o z93Y!wpL0!XN~Bny4PchM<(qUqCFRrz znW8p*Vgwvq4#(Zr1;iSHt)?7YuJ6$Tta_Zy3a+}6h-z;^ex|eo$m$`WJZ&{fJk`184(gsjK@dtcf<)aYQw&NyJlhH~7qmc2YcXuV zKhQSY0D%E$-BUNCaxbpL014QoWFSFwf)p9BC+zCUcH) z8EZ&~R4d%$c}_3mNJBZDZhzU@(x!bGv`If*7rlymFwf)bIMPfW(?h%R4upL<&+i26 z`$2~POxX8*OovH^eUAecQeoelef;sTuhDlLQ;Fun9h-)IkypqW#CA0q!UTwUAY8@> z9da(n`b{Ff3S4)vGFFGv4e982To21PT#DilS2!dDVsW`LQKNZCL2IqtLJy7T-;n99 z=m8WdY&+YF+jS74HNnV3L+&>U?EFr)9|uTGiSeVzR}alr&m9zauYI#^YVu@4KK>$9 z!Xh8CiOKTaH=5#bFRf4Fm$mzeCCWk%pO~H#3Ovt4YA+u0qQD2ky^Tr;578<~;32w& z!$WjqP81mX<;Fsu3h-n?f&VB-pB)tVJdf>+?#Ug`5*=7~lucfD^q{~c4@Z{c4R}ax z$BTM_I0p*69mtLF6gyZQJ&hd0(APS81xgG9Ik1|ki`5f-3Bnqsr017M@BQ3$e zH+gtA1|aXdL3CifPd2sceYbizvb^u39@194?~`zEBRqMZ7Czy9x`p#T-FN_FJstEL zTr1=t*gLl`{;fwf`F*iVE+0$@Y-44|j&i*)Qmo0d6JqZftK|mGb?T=USIlug^RQ_w zK<@Xr=)k(4Y--j0p7C&Gx!=pSD!r{`_hDb`4hu;Ux;er@W1+Yk_y#+|Yv=70U=k~B4vatyJii%L2E0pknu$nxB^o;Fgc^a>?KPmbG-b}*2 zSsk^(WrwclO9A`}?Q2HyGq`sI^ddu`ltG4Y9)N)mV}P$G6=4(*k*f%!;2%A_l0}$a zm^+vv3|{7oFh2)rJ5+>OP6)qz=PslSa|CxtwsV&j3NdiZs=$MY9k&QT?*-x}qz+bN zrp(En-V~IJ)tG0%Fmh69oZnVFOp2P=@&pb$f6i1o@(ia4+#hp`sG5k4~)5=N`=Scp^s{ z%A-2JNN>HfHoGU=%-KeQ-gSj793MQ(n>o@@metxv%p8_l-CRylxjc?@59WCsofC!h1B}YH9r3M`i#+cqCWE^#Mh?lGsr8X zd7?fe!q&{=vrnLHu4A4Opn$~Wjhez~zkO$oJc8`{IX4})LIZ3GTHsofq z_UeBlKxWE+zlMDE(ERn>snYzHM?$l}A!O*sq63Qz$tEu{6feh6q94Dk9Z;kbd+eW` z9ijJ8mFCYLk?e(E-YU&rz=lx?t@*S{5_pkr;qW5en6pZQ{cJ=beRk19vMYMjqZA}1 z(EMRR`s`F`)_KfqbWiTMT6AFDQ8szq(Nm>4$HS53crWsh+Kv~^2jU!6n)86%2v3fu zg-be;)yrGy^ZkXiCXxCC+Zf?6LsT!-i&$+4%BEJG@FyOQEGK--L)wZH{tWJIgeND|!Y7V#Zke(J*?>3ie%$ONEWb(>{# z{iz!z(Z>O)H;H!Y18Id92_C1k8r!B2fR#^1R`S+uP7Dy0?17@T*&a@f#$UI&G=N#M z%S%xizQv7W7hNGiKA4~bAxe{IbBIj8>S3#euwfpVh#g~|r{egey3J()q-12&Tbqp> zRJXYyfJHLx-vTL^_HG#St=Db-32&CCZX-H$MIQ>_m+CgeDAsL07|@Fhfl>w;LTdsa zfPoNWfUhUjZ4@+-t8SxUAw9g3b({GxcQADuyv)~az75iLsBW{OUfeDZCz7aYNacq8 z@_Fn&skNJSefd1`Jn`a3#y4D-#ClBLiAO*8__YF!u@dxCpq0~9XBA~W<~k>)7gY^P zTzA9z(}6-^J;(?ZJ%#ec-qGpoaYqLnz@#gDC15{}G^G+SOVGBd2y`s>V4lZgIMPra zW3S+tno6u8{oR~XxX1IHK93{KQU4ceafR4B&CAJt%CH~ zDQL_(kjW;jNzLe=TynbTz`CSt^17s_ps~oqk>z}cdPr^Oiyj9p=O}0#0rxh-lk;ie z6V9hwIOo%ifdvhuZ_4SWcodS~>5kB^DzFC-L9Wf!GJ?~u3q1@Q3y}MrFFLU9C!1Pz zzfliImiv`Gq^-E$7~I;1tXce4q${$?ufGw_RZJtpTD_67x}1uP=#lK+8ihJuJg}0M)`d zl`(N3CcJqwTm-8Q=`)40iHyaw>A?K|%9uas1fVYj=zt7`I%u<@a-z%+2QW(p`vEE> zm%%iIoEv3+!oyYzu_Xg#{*C9UI2s9M{$&6u85#A~W+Mlo%!kd(&TUW{GVLKinr_-g zSNhulv&8)8ydKcVdM6+k{Ja9$>WY>J2tx2PE#78Buj2xGk%dtFAPZ^l#|L2Ol&iz+ z_)YM$T1;v^Ln`g)ZA$@C{LLffT4ADAsukeXivmniwO;k!({QD_qp+=78m=wJ>&s7+ z$E!VW`H3n?dEWBsiLk?>Tq{?`p0{n*xnrZd#2FIyN?PvHpaped5MKKjfSnn|?b}O3 zxIqJtlfVUcWkQ@UQK=45v$A${!vB7F-2X+K5 z3#B3+3aVez0v>=68dQ_lgT6EkH0rkCsqG3(Th!*_=N*SwZ9h~}( zlU)B>g(K@VCR32HF7od-eU{^uFT{L`BegIqWidQ*?&E^i;?8-A$?)e~PJ6fMo7{tW z9>2zshVq!)3ThZlwq?HC^iz%xp5@0l(oB}!KxzY_$^=;7;ykMp^{tunlj(kDeQP?? z!4{%112UO9ekCpX5X>gdlIs?{0Jaz|T`@jd9)!1quNLi)6>cxpcQ+2*x}!2QFw@n&RV+uWuQBC+b_*z~h>(Zy~R+WD@l) z86re|>sq)hR{{Rdd3ftqv^w(A={Of14@v?jTjkM}Ub*%}4P;o>w^m^1$*OO?Ab>?$ zj-G~mX-;8j_S~p%4SFOrfF_~2TSW&J&6Q1FG&lZM4mnW#vi27-FJ9r{6P<Z@mKUZB#-SuU1I{q%xGv_gx0q%@hAp$NcF9Y1nIL=-}<`_R5r(0qzE>d6Gfec(`x$f6pa;9Q`@i1?!L9Y0u=)k(7 zY--gN4_uJUnCt||a>e~Uq^-E(e7Ls}o?KB2pKwLp!nvYuJYbXi;uYFZ&jJmu6|xBI z-IQbg!DHKmW2UFhNJ*k#^8fQsN!{sAZ^_W}O>3UT zidTgEK{}{;gvl_d;cq4+@-(%z2`z|e^S!q<~3UTS%%^&GEwH5R-CD_w~2VF^pay$az=Yt|E4^hc?$ zCjumQ^@Uiv;?E}zVd-k658`Nu(4EIb63Srd*Mi=7EPell(30{U6|*8~8cSccvs$hj zy%xI5W3a6jftdn>m-p;$aF?B%q$21NY#GUTW8-*-85dAh70lkkj#8~w+%8V?5(nRR z0P;Qtl%6%SDfA8@@5MkX=fuXQ_LK;0EhJ9z+Q)5`?`pXhweyR${OUki5aTwoM5|D& z7{(ndJEWVWO_2ACIM#V=_6&|R1)JR{XxjvN4{{IYdECm8hVmHOF=+7aSVQ`o9Ixaa z&vUwyBMs$r1`SXdqYb0(b$ESL(YgNmHtyLxo7Zuq!EDlZGZJh%*MUv-+hy}Z+_QN$ zKgf}0vguA5_KH(Q9;_R1qqP%tgL@hNGwTL-F&%6nCZTSy23Sa~8+^sbA73{x`cBjh z4ud;3T{l2pA&nMw0~vNj-Cz-1mbsL_ZgA|`#mh?YVvN0|rUJil4wWB=hSz1}ZXlI9 z<>{hbKl&pw)fGK~EQc)pdO9>I3Jv|%XsGiae3^ZaUu0T3>?ESI4(M{?kJnQ?&zsZTmzzMEC2?$VYN6U51)^HcOy7&{-TF_V+!)a&x;PMAIhdy{qWl!jx0a?mWQ+z zKl~54w-KKFPz#^%L*2spp>8}h(~de3X=Kwuih_5{?Wv#hs4Ksx9!aYlz2bcmQKNZI1@m3XX`qb35V;k81Ke;$m9Ix{f$htQRpz3RFqLHf{}9 zFMpLE^2_0iJ^UI|kRM(sIu&bT4d2wsSNb9>=tk75#Dm=0VZDOGI`4hXVTg}{}R4}7Pp?KDB!wyN!?14O6g z-X~DCzU7`%1WY@%PNKOft;WJB1YqSmV^$6-&VD&SRI&$(+Gcy?EY3a_z%1G2N2rWk zc4@vi`=p1h7D7lyarOz%Q*qEyarURGdBHknCIrr6JQE4y0h(sW9eS zKlE+|-b@a?tQQmY_=`k`u4rWdzf@BsM(4l~T^`Vj41rPx8A59UAAo@nBfYOD)nFBf zmg~?vg-z<=mDm+27PU;J^E}{=uXMf)q)n@I#?g)LXx|UR{_;bpM!6LBjxVLX<4a}v za(77~Aew3!P%R@WDst{FjvRIA?vZ0I-3`t)GHax3WFI+6jvNbqwQXWxWOmPMcVD@? zdt@4<+nA+~?5{4w@4LNp1(d4k>B^tnBC11T{Am;<2g5~v&lo`iZ%1;m3rBD{0$g6G zn37zM9EvO-4w4n%|E*F(V+Oo|SuMj3dlY4`(IweEAy(BDeC}=>B3qX-Ld2@PhNZ@7 zSw&EB<7MN!)(=$%Yrx3Zc3iEq_lFJWwg-1duLrTU&dK89eqM_^YR|Md>N3OP2iu(1 zN>%veRLtNR6vp1WrM=%8Xz%M>dyltZZ?dRsZz;&`#=(rascmHXIrZH|93vNi0~&@J zFG{zz?3!t8B7si?o>dvV3~JqI^Cq3S);OB(Q|KNXE!JxA%CX~F@?o%rK}8J_58^DO z2bIR{4T< zlXhDLg8RtpRfK6Am>dN9Yz?-}mFinzQjOr=3L{eV07@tJBbYb;FkO?5BWG{@+kN80 zfltI85bP5_sAZocH>GIf$`!MozCLUTmMzOY^dob}u46XT<$ZREDFxq+Iko!|Nr$o3+kGY5%j?8n?Hx^bBaZqWtMi}Igo z;(6xoBCc&=EYTgkA8sK_aC?vMS}NFu9L_QjrvEnp5%9H{xr0sWR{ou}*8p@i`wtq^ zgCXW)_18PF@b4gW%$M4v@oNj79lz&btc4!gqG(gen#;u#%2o)#H( zU=pWLP|yqTPq7AQdNw^4Mq{Bn>7vWjEL*HY0yi*Ghj-2!ho{pm6QkOhRuy+6J&kkQ zm_NuT`QE0VP5eu0oH)#c;)ynI0j*~3dQf2jCz5N)0v(glKs(V@@T|NsMmjQvnTDeg z6>t6?`IpXg4T%E#7?KCHItSD=4%#qUhQnI$h?n7VX>_PCHnC#>lH`6F*B4|E=)fM` zg3p69<>8+!ZCjpywPE%jHM2%R+?b&)yGk}#$V!P53t179n1$?@;6ZXBJ5!H@-O;ffGd5k?mj|N%^bG3Jb8aa*sMT_8J z?HHlr=4ynlK?&ptT};BXFhcu$Bec&Np{L>Vx}uHnPnN!|5qgAS_W7DwqoIrus$_!^ zDkTmcp)Z98rOcr(!=|(mDtS#j#$E!TWHiUC^%C%>Q3N-kPMhOLG=H>Ckn{T}%bP&O zdXh->hhfFgP`IGLEhXlZge?`31xzV;F%z{!L@)!jJk-tr>Sfq;QZMcpS9hlQG@HmI zXRiR+!LhD@e>{#Qu<8jUH(2!*O{YDBjl(#sT8jfG$}sSyX?77z!&YNUdX}SmXM&i9 zO8>QWs61G270&E;Za&4T;WE-l72Spcis{+l zkuymD^1-)goYK8+us-)X;6JLr%i;YThdiuyFGp&jHp)bZN8TAoi?A9ecqd+N`6a_s z=F2Vr&2+FQ9s@4rKNRb5_E0SCW9C?_+kpueqgx*4ZSMuH3w7^Yi zL|U^OUrqugXJrp6Xkc7l2eh;dxTt+obxh{OYqoO|1hT}Gxb6yeR-j-Q+Kph*i%`Z` zXrFDFL4@~itB|APworTS_&&g~$;bDXail5n{iTA|Vso$hE;%z94)vu44gAwp-z&I> z@qAs*k!JGcMg}`%D|f?rhqFp2=A9cE{xj#DzhgSsLQKlMa}F?(I`8cEamdd*M&pTj zXBFJBg?R_LRr8Js@IJ%CEzt`Q1+sU`yt_W1i3*y%na; zhFY?THKm>jlFLd(Czh3(PObkkSC+V5%UD@1bSD4Gj!|_}nhjFh^{|f~LSuAAKY)L- zW&|`N?tS`CBsc5H*R-&nJcwOSf)KkK3%R8vwz#WE!%XAMjHwAaW-lO-U^D#Zv}&~i z6>va|nii|pm}&0h?sTcg9^3B`%HI~=7k6RY_ILv6+$C<_IzK)3#In5Mkj%N$z z8f^c-c9*%09CLiWa56`lk}sSfXstYE3ixG$HGK_tra-&P+Qr=Sc-AiDNP}5}(UM?I zUjx?gZRj6608|;$CLzX|9FUU*YwD!%B^H<5xLbYxSX0>xqAhA<6Dz(ei|wb zR^Wp&Vmdrk{4FNM;2leM2oN(2CApO>}n)}GK^!o`E?nc<6(U_@o z3BrAz#HK|4Ez+VMk`Qy5X7_9yIW)0jJOl6n&jj?|1=EDLLbuec(+}70D;`_v6<<#F^e(WMu#Kg zFdJx!{N*yVnq!EcgI92*DRb~rL2G3$Q}LjLIA7L9DANlH zm%FpMNAldA$&qGq=MGhSjN2IkXN68=2s;@5Gc$yU>0k?Cf^UBOKO{pq0-m3mA#C?C z$7cve*~tt6?$}(0fQ+gPK@KF5AaT79;a`tW*Qe6L|IP4d9({Q~wxmRV zin7f{{-ZE9)x4qK1t`+8Xw6N26vO{H2C4BKMymOT!ksjF-Yh zVwLqqn9RITiHW#BO^7JN+kyuDazoiYfed5hHw;I2BkykHk8mw7BD|@yst6wx^MA;( z!bjErVE{%BD&2<*omn648v1qRDGK1Fqu*HK6rj=RQ;2WIXIM*1weN>T)s=;`sJaGQIulio9IX_Gyg@aYPh+5E(wJ!2GYn9`QkFH}JX-agB0%8~Zy1td+DKolW$8?y?==w5verj}W_?Y9P zt5J3$x}FMmY%aPYqbj;ee-+X7bhzA7bX7Ni=&FZ7Sakg=Jetp0@4=SNMAxHm)Hjo} ziheD`*S+O~RsF}>Psjig6rz|GH(ou2Mh(nazekpCN6t#hh=tc_bXmq%`sFhG%Rq)P zz#4|5Um)+X0J|p@2dtDeQ7%w408_+E1=EgTRL2L^Jvq{pp!(-P0Wqj@0(K&(9?kHd z8B`ZD9VRoV{u-2+8dMkgnB#-0QFbDz{yRLbxuA-Ss-P-;R0P%Uz~z>Ls=5ILRqgs= zLG>cg4j)u6#g@#VYM#&?{SkH}G}I;sxeWtW?#Ue(ibU?f01~xNB6ITvZf?lfd~uLn zpqZ$bN8^Xjq!Z|H6I}-K!XPVq+y%{t+b@QZ+-$#iQ`3m}pgL{DJ&Ht#vAaQAGn|8G zWRnYr7B@ilv62{_$S1ya+B$gi-Bl$A~uc^#MIjvd+Jk9Asf%lER23t&qUM z_D@pC^di~d%JkVlnK08ZGDWwcc(F{QE5i~($@c!$DL^bWZ&rBb8thuYc9+%rIac{p z;+I|hKEpA@ z^Zpb^n#sGFG_!Vva30o)RBzGZWLBG*>K)2-XjiIt2)ipp41BXK55TJ#tg2K2aSjY_3j}3gzKK z9S*zI4qs3qPzJalTJ7l3S)eKiWiRw-315pWImIRq&N1%HqgjaY(GN&%nk<*up4(yTBvdP&tL}oZ*FJqa; zG{L+Kw@`1Azg$IM=iv%ni#|@$@Q~X3dPGT+JEf?;YrG_PW(jij_3F34y^R9s#W1aa z#Ie)5g*$dyH}2zDOv~MHufzDl9&(uw4=wTVuSZ%}RP(3vpoq>vo>cl6>F8k>zsV^^n>w7rhUNbGY0Of!qjBE~kZ0xSVd`TuwIz zewGC3b35D@J<7=MaB%kHV0pZ>6_YY^&VKAe+tm`4S7PBV=hxEbADK*I?3~1yg8Xo< z=)n4+Y--gHkM(e5`QZ`|X)Au%3->m{lOJl~6Mm>$I6u^l2XaO<5s+<$K!yEt`{jNf zc}F<}D>*EQm00~-fJu(BZqp6l_pKHO zM&X0GmEqx9soq-<{3Q$690Wo&7OqKqzeq6O?r~Zh9eIl$6^*l7hV7PFvL=9$*-oQe zGC0>J1#1i~Rki0Hj2PYe!On4)%>=vsKg-ik23ijOtGhg~(L%k}3tuKAVwr#aG; zmHVxN*5Y)!^q)AN&SgMGh|1;h0q(&(k6-6VLwTGgd^^sfeHHR{N#ip3Gw!K8gO78h znGB`}Xf-Ub(#3gHC*Y4+M56Z;%CI1o`frBIwA4=?p&5fedN+)ZkM5#iT_}zX$#^Y3Wj9t(F~D9o zLr#~klXm@R4JZ#>Z?#8HrgMtg@XE#k2EZ#yUk$83j?GjFysv6tA`?dJHe1+ zv?0X=EdUYxs*{96(AXxD#TE)?9-!ITT+oIUb8^Wer^%9OiBJ?B*d>B&@-7jkqF6Hg z!Zt1O!{zA}9-h$C2p`$$A+;9?dGV1~!M%<6v`En6Cl(31gz;GLLdlkA#+7EJ(d*$#HVxE_6e=PrD;p_Uf3Goe;PBa;jq6z`YYK|kzKR(=QV7ZK6*&w8a^9OXo;iW&mv zrvb^}9!DoLBs<|Th9WP0S_sQ}scdT1OXqtyvb^*F4{0l2x)APdgeNc6!Y8~`w{Tvn z8;?XU^%>H5YY;hjE#5!3*ZwK5*QTfTXcEF+wglXjuop}?0B-}qwF+dm+=+4OdO(;KP=8wQGadfmaBobL6F$N=)wOWBsnaEF9I91*j?qHPiEvb}m z1}i1{2KG4aMN=Hvvc|;z=hut%iCSS(sWx62gOC0wvn3l0Uyn+@e&pv%jD#N|xfltG zzv*#>_n%*Z+E=yo@(DN@xK^l)0hA$gu|lx`2Tucw%S(996Z6aE>1sszjTGfq zeo@Hpln8r+ij`n6v}ZPE58&4)w!VC#QZMa(+irJXMhvXE26GoBNnvMsbQFC|Nou#$ zM+)1d{M%q$)zJa#u)zgT`6_@svs|6Poq)bvSCqrW(Hh(qu%O~tL6WNP%9qCmM<<3# zLsE_1hy~^0$?USr*$=cfM>rMMm$DW|2FmotZQ=^knXz0V&NTWTZhMkahz-d>&@$I9=?bfeXx}KY8GHP!y zjqrq{0}SEvwXfmp;j=8u&wJ&pLSeDA_Tu%zxo2IeIO7|&=7mqJ@~}c!dGruG6;dBk z6K+fA)U>}iI7p8`qog^p21`YWCb;)09;mA=?RVYY|-Wn+A;>Fvym+MQ# z@AZY#i||sZn3k%g9hJ*V1^iI!u4RSO;c}r|8(UJx?^)txRj-yxg{6gPpi-+X!*p=f6?^DEI4|pR4t7SmWFnVV;eKF)>)WlY!YdP8W#2?t*@vCx&pyp z?ok*)~uu zjt!1%D-^5SCw72CE-RdgKp^;IVXRW0HBm#49Vtn_MCrr?2$#iuw(Tg^01e(o+w;X& z!OWAzy>?Y53OkEqVm2IvjWPAotYTrTv{QA_w}NZiaHib0vr@gRHeMVoZBwj^sq$pW z>PaWcf0yD8oaezDJF8Z&R3$s&w(11|NK6Ee=2>R`?9Z<$D~2@F8;t#GVeI%^N(NBw zqBfyxR}pdZO@2R#XfBmcfw^=|lQy*kZTc3e(vrVuY2|P8NFnVzn~-*+@+bT-U6U?o z*l4unb}3qzwhdifsbC8HFb@{;f20Zdr{d5t_i4!ADICnU#+c$`rXF_YE`pmcHo?t# zZ6CRMJT%&WZ>^>58OTim4uf7QEH@1o)EfP;dNuC4b#SCOw!M_`64vE?@lU`27{J~m zhAb#v;kD-%w}339JxlD3$v6i17?#IwExOoH$-ERk$KF5%qAGVyT-OdFoc329r&XIW z@DQW_23k3}c1|<;MBc`HRuM|9lvY=`X99)8JxoTp=r1T|Y!B0%m;odo=2ddO-Mll! zw=ZZUuDcSj`oD7r|!d9?qiMLhhtQo*oX5t_@vIzM~;HC6_0@zW4;8rY-2xntf6<1FdwF{i-=9pWDhu{j>0>!m{aRH9>44&^YzjW0wOSy8QCK<%a3yB;oQC^)(rB zpLg-ea#O%beaDF6>q-56mmYhpi~}n>%6*p4Z}ma3RHGiCh$=oF zrrrQjny^V{h_hNcdj{5%S^lx*RB#~MMJhXR%Wup@mK9FfRTwG_7biwx%~XfACBD}N zRNz#@>ARfMvx#rXO_HuVWe0a>4oaqjvdA7E_jyu3Sh4Q71fFluv+A;TDrVk z!(;a4)&cnld81i)Bf!uFm&lsLEVePW9x4wHFW-hL0lBN?5?~s5^U@W?!MYk#X3;e^ zx!N?o)tKxjgQs01{4>7TBLl11p5H+8wgA_r#h!c$EcW(RK4VF3uBGrZgB(n;!|s~> zKoi`&@qdQPTDth3!cmGP4oM$f$~Xt5jXxu$$b3KBguNE|hOnNp8eUQ@VbEfVV)HcU zb(I`34iG+*&~5|m?yasEu^Z+Z+~$D*`Q3>DQFwZ|4d!lnXxbio#PHlpduIUvF2XXv zyZwFQrySJqTmIA&tU!Q)zEHrs;QtoWER4`FT{4Z5Kui_TzPQx4cICSM6~#5Bp%sI} z{iV|2x)sHt75xM2;J>9ceWl@*tJd@llolfo>VJ!=WP~@+d=$2iLSeL29j^5jE{9i% zG3@s(>sxkwp;o*cs!Hx1)XV_47@HU!b?&a`6uf_b--n%xTs6FU@c6<0b>OV4)(sB!53D_Y z-RiXitq8cXO#=39?q9in#p?B|`|}A1gRnF>FtDa??eS|?4-6Lv2G{nlTiw5U-MZq6 zH7ojyYgesYvu52;^A_xHtAMN4uRcDPfGbNYR+I+Tt|=bBa;SgpI`GZGf#Rxx6>Ixe z75mn$g6kmR$~Ehn7jQ*;1ngUjL8h;N{i-##fD~>-SQg<0ivk#&bjZ`3FBaPmq3w9l z=}P$TrMi0df3g1mV!fEm{x8<2%+~*(y>|hV?5gU;10;cTUJ#NAp?Op~B=g8rbv^qr zNhVB^NfW0*c&kLfy7-PKfe&t!t}qHytw?O&AezFfE>f}jY9pr{~%L>g=knnmp)yAIwah{a9=5wfA1{y>ZrWob}4Hs!ms1 zpnSNW^-7Cjiqe-;6op8*g3wgXQ_4bb{YHcAt$l(c$#DueM?KMEBK^G|=4cD^2Q{`|3iBIEed-z?AMQ&eP1La}j

tz~d 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 literal 0 HcmV?d00001 diff --git a/f33-branch/.doctrees/pylorax.doctree b/f33-branch/.doctrees/pylorax.doctree new file mode 100644 index 0000000000000000000000000000000000000000..e4ed89d38694850d8691be0ef5d0c9353812b605 GIT binary patch literal 617363 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 I<8S!?0}i?;Z2$lO literal 0 HcmV?d00001 diff --git a/f33-branch/README b/f33-branch/README new file mode 100644 index 00000000..615e8738 --- /dev/null +++ b/f33-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/f33-branch/_modules/composer/cli.html b/f33-branch/_modules/composer/cli.html new file mode 100644 index 00000000..51d4c38a --- /dev/null +++ b/f33-branch/_modules/composer/cli.html @@ -0,0 +1,259 @@ + + + + + + + + + + + composer.cli — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/composer/cli/blueprints.html b/f33-branch/_modules/composer/cli/blueprints.html new file mode 100644 index 00000000..c369fa53 --- /dev/null +++ b/f33-branch/_modules/composer/cli/blueprints.html @@ -0,0 +1,779 @@ + + + + + + + + + + + composer.cli.blueprints — Lorax 33.10 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(pretty_diff_entry(diff)) + + return rc
+ +
[docs]def pretty_dict(d): + """Return the dict as a human readable single line + + :param d: key/values + :type d: dict + :returns: String of the dict's keys and values + :rtype: str + + key="str", key="str1,str2", ... + """ + result = [] + for k in d: + if type(d[k]) == type(""): + result.append('%s="%s"' % (k, d[k])) + elif type(d[k]) == type([]) and type(d[k][0]) == type(""): + result.append('%s="%s"' % (k, ", ".join(d[k]))) + elif type(d[k]) == type([]) and type(d[k][0]) == type({}): + result.append('%s="%s"' % (k, pretty_dict(d[k]))) + return " ".join(result)
+ +
[docs]def dict_names(lst): + """Return comma-separated list of the dict's name/user fields + + :param d: key/values + :type d: dict + :returns: String of the dict's keys and values + :rtype: str + + root, norm + """ + if "user" in lst[0]: + field_name = "user" + elif "name" in lst[0]: + field_name = "name" + else: + # Use first fields in sorted keys + field_name = sorted(lst[0].keys())[0] + + return ", ".join(d[field_name] for d in lst)
+ +
[docs]def pretty_diff_entry(diff): + """Generate nice diff entry string. + + :param diff: Difference entry dict + :type diff: dict + :returns: Nice string + """ + if diff["old"] and diff["new"]: + change = "Changed" + elif diff["new"] and not diff["old"]: + change = "Added" + elif diff["old"] and not diff["new"]: + change = "Removed" + else: + change = "Unknown" + + if diff["old"]: + name = list(diff["old"].keys())[0] + elif diff["new"]: + name = list(diff["new"].keys())[0] + else: + name = "Unknown" + + def details(diff): + if change == "Changed": + if type(diff["old"][name]) == type(""): + if name == "Description" or " " in diff["old"][name]: + return '"%s" -> "%s"' % (diff["old"][name], diff["new"][name]) + else: + return "%s -> %s" % (diff["old"][name], diff["new"][name]) + elif name in ["Module", "Package"]: + return "%s %s -> %s" % (diff["old"][name]["name"], diff["old"][name]["version"], + diff["new"][name]["version"]) + elif type(diff["old"][name]) == type([]): + if type(diff["old"][name][0]) == type(""): + return "%s -> %s" % (" ".join(diff["old"][name]), " ".join(diff["new"][name])) + elif type(diff["old"][name][0]) == type({}): + # Lists of dicts are too long to display in detail, just show their names + return "%s -> %s" % (dict_names(diff["old"][name]), dict_names(diff["new"][name])) + elif type(diff["old"][name]) == type({}): + return "%s -> %s" % (pretty_dict(diff["old"][name]), pretty_dict(diff["new"][name])) + else: + return "Unknown" + elif change == "Added": + if name in ["Module", "Package"]: + return "%s %s" % (diff["new"][name]["name"], diff["new"][name]["version"]) + elif name in ["Group"]: + return diff["new"][name]["name"] + elif type(diff["new"][name]) == type(""): + return diff["new"][name] + elif type(diff["new"][name]) == type([]): + if type(diff["new"][name][0]) == type(""): + return " ".join(diff["new"][name]) + elif type(diff["new"][name][0]) == type({}): + # Lists of dicts are too long to display in detail, just show their names + return dict_names(diff["new"][name]) + elif type(diff["new"][name]) == type({}): + return pretty_dict(diff["new"][name]) + else: + return "unknown/todo: %s" % type(diff["new"][name]) + elif change == "Removed": + if name in ["Module", "Package"]: + return "%s %s" % (diff["old"][name]["name"], diff["old"][name]["version"]) + elif name in ["Group"]: + return diff["old"][name]["name"] + elif type(diff["old"][name]) == type(""): + return diff["old"][name] + elif type(diff["old"][name]) == type([]): + if type(diff["old"][name][0]) == type(""): + return " ".join(diff["old"][name]) + elif type(diff["old"][name][0]) == type({}): + # Lists of dicts are too long to display in detail, just show their names + return dict_names(diff["old"][name]) + elif type(diff["old"][name]) == type({}): + return pretty_dict(diff["old"][name]) + else: + return "unknown/todo: %s" % type(diff["new"][name]) + + return change + " " + name + " " + 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/f33-branch/_modules/composer/cli/cmdline.html b/f33-branch/_modules/composer/cli/cmdline.html new file mode 100644 index 00000000..15100bd0 --- /dev/null +++ b/f33-branch/_modules/composer/cli/cmdline.html @@ -0,0 +1,251 @@ + + + + + + + + + + + composer.cli.cmdline — Lorax 33.10 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="1", 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/f33-branch/_modules/composer/cli/compose.html b/f33-branch/_modules/composer/cli/compose.html new file mode 100644 index 00000000..2bf6847f --- /dev/null +++ b/f33-branch/_modules/composer/cli/compose.html @@ -0,0 +1,892 @@ + + + + + + + + + + + composer.cli.compose — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.compose

+#
+# Copyright (C) 2018-2020 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
+import toml
+
+from composer import http_client as client
+from composer.cli.help import compose_help
+from composer.cli.utilities import argify, handle_api_result, packageNEVRA, get_arg
+
+
[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 + + compose_cmd expects api to be passed. eg. + + {"version": 1, "backend": "lorax-composer"} + + """ + result = client.get_url_json(opts.socket, "/api/status") + # Get the api version and fall back to 0 if it fails. + api_version = result.get("api", "0") + backend = result.get("backend", "unknown") + api = {"version": api_version, "backend": backend} + + 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, + "start-ostree": compose_ostree, + } + 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, api=api)
+ +
[docs]def get_size(args): + """Return optional --size argument, and remaining args + + :param args: list of arguments + :type args: list of strings + :returns: (args, size) + :rtype: tuple + + - check size argument for int + - check other args for --size in wrong place + - raise error? Or just return 0? + - no size returns 0 in size + - multiply by 1024**2 to make it easier on users to specify large sizes + + """ + args, value = get_arg(args, "--size", int) + value = value * 1024**2 if value is not None else 0 + return (args, value)
+ +
[docs]def get_parent(args): + """Return optional --parent argument, and remaining args + + :param args: list of arguments + :type args: list of strings + :returns: (args, parent) + :rtype: tuple + """ + args, value = get_arg(args, "--parent") + value = value if value is not None else "" + return (args, value)
+ +
[docs]def get_ref(args): + """Return optional --ref argument, and remaining args + + :param args: list of arguments + :type args: list of strings + :returns: (args, parent) + :rtype: tuple + """ + args, value = get_arg(args, "--ref") + value = value if value is not None else "" + return (args, value)
+ +
[docs]def compose_list(socket_path, api_version, args, show_json=False, testmode=0, api=None): + """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, api=None): + """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, api=None): + """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"] if t["enabled"]))
+ +
[docs]def compose_start(socket_path, api_version, args, show_json=False, testmode=0, api=None): + """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 + :param api: Details about the API server, "version" and "backend" + :type api: dict + + compose start [--size XXX] <blueprint-name> <compose-type> [<image-name> <provider> <profile> | <image-name> <profile.toml>] + """ + if api == None: + log.error("Missing api version/backend") + return 1 + + # Get the optional size before checking other parameters + try: + args, size = get_size(args) + except (RuntimeError, ValueError) as e: + log.error(str(e)) + return 1 + + 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 + if len(args) == 3: + log.error("start is missing the provider and profile details") + return 1 + + config = { + "blueprint_name": args[0], + "compose_type": args[1], + "branch": "master" + } + if size > 0: + if api["backend"] == "lorax-composer": + log.warning("lorax-composer does not support --size, it will be ignored.") + else: + config["size"] = size + + if len(args) == 4: + config["upload"] = {"image_name": args[2]} + # profile TOML file (maybe) + try: + config["upload"].update(toml.load(args[3])) + except toml.TomlDecodeError as e: + log.error(str(e)) + return 1 + elif len(args) == 5: + config["upload"] = { + "image_name": args[2], + "provider": args[3], + "profile": args[4] + } + + 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"]) + + if "upload_id" in result and result["upload_id"]: + print ("Upload %s added to the upload queue" % result["upload_id"]) + + return rc
+ +
[docs]def compose_ostree(socket_path, api_version, args, show_json=False, testmode=0, api=None): + """Start a new ostree 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 + :param api: Details about the API server, "version" and "backend" + :type api: dict + + compose start-ostree [--size XXXX] [--parent PARENT] [--ref REF] <BLUEPRINT> <TYPE> [<IMAGE-NAME> <PROFILE.TOML>] + """ + if api == None: + log.error("Missing api version/backend") + return 1 + + if api["backend"] == "lorax-composer": + log.warning("lorax-composer doesn not support start-ostree.") + return 1 + + # Get the optional size before checking other parameters + try: + args, size = get_size(args) + args, parent = get_parent(args) + args, ref = get_ref(args) + except (RuntimeError, ValueError) as e: + log.error(str(e)) + return 1 + + if len(args) == 0: + log.error("start-ostree is missing the blueprint name, output type, and ostree details") + return 1 + if len(args) == 1: + log.error("start-ostree is missing the output type") + return 1 + if len(args) == 3: + log.error("start-ostree is missing the provider TOML file") + return 1 + + config = { + "blueprint_name": args[0], + "compose_type": args[1], + "branch": "master", + "ostree": {"ref": ref, "parent": parent}, + } + if size > 0: + config["size"] = size + + if len(args) == 4: + config["upload"] = {"image_name": args[2]} + # profile TOML file (maybe) + try: + config["upload"].update(toml.load(args[3])) + except toml.TomlDecodeError as e: + log.error(str(e)) + return 1 + + 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"]) + + if "upload_id" in result and result["upload_id"]: + print ("Upload %s added to the upload queue" % result["upload_id"]) + + return rc
+ +
[docs]def compose_log(socket_path, api_version, args, show_json=False, testmode=0, api=None): + """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, api=None): + """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, api=None): + """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, api=None): + """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, api=None): + """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, api=None): + """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, api=None): + """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, api=None): + """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/f33-branch/_modules/composer/cli/modules.html b/f33-branch/_modules/composer/cli/modules.html new file mode 100644 index 00000000..b49ae556 --- /dev/null +++ b/f33-branch/_modules/composer/cli/modules.html @@ -0,0 +1,249 @@ + + + + + + + + + + + composer.cli.modules — Lorax 33.10 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/f33-branch/_modules/composer/cli/projects.html b/f33-branch/_modules/composer/cli/projects.html new file mode 100644 index 00000000..0d45ec87 --- /dev/null +++ b/f33-branch/_modules/composer/cli/projects.html @@ -0,0 +1,311 @@ + + + + + + + + + + + composer.cli.projects — Lorax 33.10 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/f33-branch/_modules/composer/cli/providers.html b/f33-branch/_modules/composer/cli/providers.html new file mode 100644 index 00000000..ce431203 --- /dev/null +++ b/f33-branch/_modules/composer/cli/providers.html @@ -0,0 +1,523 @@ + + + + + + + + + + + composer.cli.providers — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.providers

+#
+# 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/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import json
+import toml
+import os
+
+from composer import http_client as client
+from composer.cli.help import providers_help
+from composer.cli.utilities import handle_api_result, toml_filename
+
+
[docs]def providers_cmd(opts): + """Process providers commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + + This dispatches the providers commands to a function + """ + cmd_map = { + "list": providers_list, + "info": providers_info, + "show": providers_show, + "push": providers_push, + "save": providers_save, + "delete": providers_delete, + "template": providers_template + } + if opts.args[1] == "help" or opts.args[1] == "--help": + print(providers_help) + return 0 + elif opts.args[1] not in cmd_map: + log.error("Unknown providers 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 providers_list(socket_path, api_version, args, show_json=False, testmode=0): + """Return the list of providers + + :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 + + providers list + """ + api_route = client.api_url(api_version, "/upload/providers") + r = client.get_url_json(socket_path, api_route) + results = r["providers"] + if not results: + return 0 + + if show_json: + print(json.dumps(results, indent=4)) + else: + if len(args) == 1: + if args[0] not in results: + log.error("%s is not a valid provider", args[0]) + return 1 + print("\n".join(sorted(results[args[0]]["profiles"].keys()))) + else: + print("\n".join(sorted(results.keys()))) + + return 0
+ +
[docs]def providers_info(socket_path, api_version, args, show_json=False, testmode=0): + """Show information about each provider + + :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 + + providers info <PROVIDER> + """ + if len(args) == 0: + log.error("info is missing the provider name") + return 1 + + api_route = client.api_url(api_version, "/upload/providers") + r = client.get_url_json(socket_path, api_route) + results = r["providers"] + if not results: + return 0 + + if show_json: + print(json.dumps(results, indent=4)) + else: + if args[0] not in results: + log.error("%s is not a valid provider", args[0]) + return 1 + p = results[args[0]] + print("%s supports these image types: %s" % (p["display"], ", ".join(p["supported_types"]))) + print("Settings:") + for k in p["settings-info"]: + f = p["settings-info"][k] + print(" %-20s: %s is a %s" % (k, f["display"], f["type"])) + + return 0
+ +
[docs]def providers_show(socket_path, api_version, args, show_json=False, testmode=0): + """Return details about a provider + + :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 + + providers show <provider> <profile> + """ + if len(args) == 0: + log.error("show is missing the provider name") + return 1 + if len(args) == 1: + log.error("show is missing the profile name") + return 1 + + api_route = client.api_url(api_version, "/upload/providers") + r = client.get_url_json(socket_path, api_route) + results = r["providers"] + if not results: + return 0 + + if show_json: + print(json.dumps(results, indent=4)) + else: + if args[0] not in results: + log.error("%s is not a valid provider", args[0]) + return 1 + if args[1] not in results[args[0]]["profiles"]: + log.error("%s is not a valid %s profile", args[1], args[0]) + return 1 + + # Print the details for this profile + # fields are different for each provider, so we just print out the key:values + for k in results[args[0]]["profiles"][args[1]]: + print("%s: %s" % (k, results[args[0]]["profiles"][args[1]][k])) + return 0
+ +
[docs]def providers_push(socket_path, api_version, args, show_json=False, testmode=0): + """Add a new provider profile or overwrite an existing one + + :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 + + providers push <profile.toml> + + """ + if len(args) == 0: + log.error("push is missing the profile TOML file") + return 1 + if not os.path.exists(args[0]): + log.error("Missing profile TOML file: %s", args[0]) + return 1 + + api_route = client.api_url(api_version, "/upload/providers/save") + profile = toml.load(args[0]) + result = client.post_url_json(socket_path, api_route, json.dumps(profile)) + return handle_api_result(result, show_json)[0]
+ +
[docs]def providers_save(socket_path, api_version, args, show_json=False, testmode=0): + """Save a provider's profile 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 + :param testmode: unused in this function + :type testmode: int + + providers save <provider> <profile> + + """ + if len(args) == 0: + log.error("save is missing the provider name") + return 1 + if len(args) == 1: + log.error("save is missing the profile name") + return 1 + + api_route = client.api_url(api_version, "/upload/providers") + r = client.get_url_json(socket_path, api_route) + results = r["providers"] + if not results: + return 0 + + if show_json: + print(json.dumps(results, indent=4)) + else: + if args[0] not in results: + log.error("%s is not a valid provider", args[0]) + return 1 + if args[1] not in results[args[0]]["profiles"]: + log.error("%s is not a valid %s profile", args[1], args[0]) + return 1 + + profile = { + "provider": args[0], + "profile": args[1], + "settings": results[args[0]]["profiles"][args[1]] + } + open(toml_filename(args[1]), "w").write(toml.dumps(profile)) + + return 0
+ +
[docs]def providers_delete(socket_path, api_version, args, show_json=False, testmode=0): + """Delete a profile from a provider + + :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 + + providers delete <provider> <profile> + + """ + if len(args) == 0: + log.error("delete is missing the provider name") + return 1 + if len(args) == 1: + log.error("delete is missing the profile name") + return 1 + + api_route = client.api_url(api_version, "/upload/providers/delete/%s/%s" % (args[0], args[1])) + result = client.delete_url_json(socket_path, api_route) + return handle_api_result(result, show_json)[0]
+ +
[docs]def providers_template(socket_path, api_version, args, show_json=False, testmode=0): + """Return a TOML template for setting the provider's fields + + :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 + + providers template <provider> + """ + if len(args) == 0: + log.error("template is missing the provider name") + return 1 + + api_route = client.api_url(api_version, "/upload/providers") + r = client.get_url_json(socket_path, api_route) + results = r["providers"] + if not results: + return 0 + + if show_json: + print(json.dumps(results, indent=4)) + return 0 + + if args[0] not in results: + log.error("%s is not a valid provider", args[0]) + return 1 + + template = {"provider": args[0]} + settings = results[args[0]]["settings-info"] + template["settings"] = dict([(k, settings[k]["display"]) for k in settings]) + print(toml.dumps(template)) + + return 0
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/composer/cli/sources.html b/f33-branch/_modules/composer/cli/sources.html new file mode 100644 index 00000000..dc2ef070 --- /dev/null +++ b/f33-branch/_modules/composer/cli/sources.html @@ -0,0 +1,353 @@ + + + + + + + + + + + composer.cli.sources — Lorax 33.10 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/f33-branch/_modules/composer/cli/status.html b/f33-branch/_modules/composer/cli/status.html new file mode 100644 index 00000000..45005e92 --- /dev/null +++ b/f33-branch/_modules/composer/cli/status.html @@ -0,0 +1,257 @@ + + + + + + + + + + + composer.cli.status — Lorax 33.10 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/f33-branch/_modules/composer/cli/upload.html b/f33-branch/_modules/composer/cli/upload.html new file mode 100644 index 00000000..544d7cd6 --- /dev/null +++ b/f33-branch/_modules/composer/cli/upload.html @@ -0,0 +1,478 @@ + + + + + + + + + + + composer.cli.upload — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for composer.cli.upload

+#
+# 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/>.
+#
+import logging
+log = logging.getLogger("composer-cli")
+
+import json
+import toml
+import os
+
+from composer import http_client as client
+from composer.cli.help import upload_help
+from composer.cli.utilities import handle_api_result
+
+
[docs]def upload_cmd(opts): + """Process upload commands + + :param opts: Cmdline arguments + :type opts: argparse.Namespace + :returns: Value to return from sys.exit() + :rtype: int + + This dispatches the upload commands to a function + """ + cmd_map = { + "list": upload_list, + "info": upload_info, + "start": upload_start, + "log": upload_log, + "cancel": upload_cancel, + "delete": upload_delete, + "reset": upload_reset, + } + if opts.args[1] == "help" or opts.args[1] == "--help": + print(upload_help) + return 0 + elif opts.args[1] not in cmd_map: + log.error("Unknown upload 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 upload_list(socket_path, api_version, args, show_json=False, testmode=0): + """Return the composes and their associated upload uuids and status + + :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 + + upload list + """ + api_route = client.api_url(api_version, "/compose/finished") + r = client.get_url_json(socket_path, api_route) + results = r["finished"] + if not results: + return 0 + + if show_json: + print(json.dumps(results, indent=4)) + else: + compose_fmt = "{id} {queue_status} {blueprint} {version} {compose_type}" + upload_fmt = ' {uuid} "{image_name}" {provider_name} {status}' + for c in results: + print(compose_fmt.format(**c)) + print("\n".join(upload_fmt.format(**u) for u in c["uploads"])) + print() + + return 0
+ +
[docs]def upload_info(socket_path, api_version, args, show_json=False, testmode=0): + """Return detailed information about the upload + + :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 + + upload info <uuid> + + This returns information about the upload, including uuid, name, status, service, and image. + """ + if len(args) == 0: + log.error("info is missing the upload uuid") + return 1 + + api_route = client.api_url(api_version, "/upload/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 + + image_path = result["upload"]["image_path"] + print("%s %-8s %-15s %-8s %s" % (result["upload"]["uuid"], + result["upload"]["status"], + result["upload"]["image_name"], + result["upload"]["provider_name"], + os.path.basename(image_path) if image_path else "UNFINISHED")) + + return rc
+ +
[docs]def upload_start(socket_path, api_version, args, show_json=False, testmode=0): + """Start upload up a build uuid 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 + + upload start <build-uuid> <image-name> [<provider> <profile> | <profile.toml>] + """ + if len(args) == 0: + log.error("start is missing the compose build id") + return 1 + if len(args) == 1: + log.error("start is missing the image name") + return 1 + if len(args) == 2: + log.error("start is missing the provider and profile details") + return 1 + + body = {"image_name": args[1]} + if len(args) == 3: + try: + body.update(toml.load(args[2])) + except toml.TomlDecodeError as e: + log.error(str(e)) + return 1 + elif len(args) == 4: + body["provider"] = args[2] + body["profile"] = args[3] + else: + log.error("start has incorrect number of arguments") + return 1 + + api_route = client.api_url(api_version, "/compose/uploads/schedule/%s" % args[0]) + result = client.post_url_json(socket_path, api_route, json.dumps(body)) + (rc, exit_now) = handle_api_result(result, show_json) + if exit_now: + return rc + + print("Upload %s added to the queue" % result["upload_id"]) + return rc
+ +
[docs]def upload_log(socket_path, api_version, args, show_json=False, testmode=0): + """Return the upload 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 + + upload log <build-uuid> + """ + if len(args) == 0: + log.error("log is missing the upload uuid") + return 1 + + api_route = client.api_url(api_version, "/upload/log/%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 + + print("Upload log for %s:\n" % result["upload_id"]) + print(result["log"]) + + return 0
+ +
[docs]def upload_cancel(socket_path, api_version, args, show_json=False, testmode=0): + """Cancel the queued or running upload + + :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 + + upload cancel <build-uuid> + """ + if len(args) == 0: + log.error("cancel is missing the upload uuid") + return 1 + + api_route = client.api_url(api_version, "/upload/cancel/%s" % args[0]) + result = client.delete_url_json(socket_path, api_route) + return handle_api_result(result, show_json)[0]
+ +
[docs]def upload_delete(socket_path, api_version, args, show_json=False, testmode=0): + """Delete an upload and remove it from the build + + :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 + + upload delete <build-uuid> + """ + if len(args) == 0: + log.error("delete is missing the upload uuid") + return 1 + + api_route = client.api_url(api_version, "/upload/delete/%s" % args[0]) + result = client.delete_url_json(socket_path, api_route) + return handle_api_result(result, show_json)[0]
+ +
[docs]def upload_reset(socket_path, api_version, args, show_json=False, testmode=0): + """Reset the upload and execute it again + + :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 + + upload reset <build-uuid> + """ + if len(args) == 0: + log.error("reset is missing the upload uuid") + return 1 + + api_route = client.api_url(api_version, "/upload/reset/%s" % args[0]) + result = client.post_url_json(socket_path, api_route, json.dumps({})) + return handle_api_result(result, show_json)[0]
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/composer/cli/utilities.html b/f33-branch/_modules/composer/cli/utilities.html new file mode 100644 index 00000000..91bb3a5b --- /dev/null +++ b/f33-branch/_modules/composer/cli/utilities.html @@ -0,0 +1,324 @@ + + + + + + + + + + + composer.cli.utilities — Lorax 33.10 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 = int(not result["status"]) + else: + rc = int(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"])
+ +
[docs]def get_arg(args, name, argtype=None): + """Return optional value from args, and remaining args + + :param args: list of arguments + :type args: list of strings + :param name: The argument to remove from the args list + :type name: string + :param argtype: Type to use for checking the argument value + :type argtype: type + :returns (args, value) + :rtype: tuple + + This removes the optional argument and value from the argument list, returns the new list, + and the value of the argument. + """ + try: + idx = args.index(name) + if len(args) < idx+2: + raise RuntimeError(f"{name} is missing the value") + value = args[idx+1] + except ValueError: + return (args, None) + + if argtype: + value = argtype(value) + + return (args[:idx]+args[idx+2:], value)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/composer/http_client.html b/f33-branch/_modules/composer/http_client.html new file mode 100644 index 00000000..9c147bf2 --- /dev/null +++ b/f33-branch/_modules/composer/http_client.html @@ -0,0 +1,459 @@ + + + + + + + + + + + composer.http_client — Lorax 33.10 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/f33-branch/_modules/composer/unix_socket.html b/f33-branch/_modules/composer/unix_socket.html new file mode 100644 index 00000000..a859b448 --- /dev/null +++ b/f33-branch/_modules/composer/unix_socket.html @@ -0,0 +1,262 @@ + + + + + + + + + + + composer.unix_socket — Lorax 33.10 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*5): + """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*5): + """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 + + NOTE: retries are disabled for these connections, they are never useful + """ + super(UnixHTTPConnectionPool, self).__init__('localhost', timeout=timeout, retries=False) + 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/f33-branch/_modules/index.html b/f33-branch/_modules/index.html new file mode 100644 index 00000000..261849fb --- /dev/null +++ b/f33-branch/_modules/index.html @@ -0,0 +1,250 @@ + + + + + + + + + + + Overview: module code — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + + + +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/lifted/config.html b/f33-branch/_modules/lifted/config.html new file mode 100644 index 00000000..1c23ee37 --- /dev/null +++ b/f33-branch/_modules/lifted/config.html @@ -0,0 +1,234 @@ + + + + + + + + + + + lifted.config — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for lifted.config

+#
+# 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/>.
+#
+from pylorax.sysutils import joinpaths
+
+
[docs]def configure(conf): + """Add lifted settings to the configuration + + :param conf: configuration object + :type conf: ComposerConfig + :returns: None + + This uses the composer.share_dir and composer.lib_dir as the base + directories for the settings. + """ + share_dir = conf.get("composer", "share_dir") + lib_dir = conf.get("composer", "lib_dir") + + conf.add_section("upload") + conf.set("upload", "providers_dir", joinpaths(share_dir, "/lifted/providers/")) + conf.set("upload", "queue_dir", joinpaths(lib_dir, "/upload/queue/")) + conf.set("upload", "settings_dir", joinpaths(lib_dir, "/upload/settings/"))
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/lifted/providers.html b/f33-branch/_modules/lifted/providers.html new file mode 100644 index 00000000..33e84a5b --- /dev/null +++ b/f33-branch/_modules/lifted/providers.html @@ -0,0 +1,444 @@ + + + + + + + + + + + lifted.providers — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for lifted.providers

+#
+# 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/>.
+#
+
+from glob import glob
+import os
+import re
+import stat
+
+import pylorax.api.toml as toml
+
+
+def _get_profile_path(ucfg, provider_name, profile, exists=True):
+    """Helper to return the directory and path for a provider's profile file
+
+    :param ucfg: upload config
+    :type ucfg: object
+    :param provider_name: the name of the cloud provider, e.g. "azure"
+    :type provider_name: str
+    :param profile: the name of the profile to save
+    :type profile: str != ""
+    :returns: Full path of the profile .toml file
+    :rtype: str
+    :raises: ValueError when passed invalid settings or an invalid profile name
+    :raises: RuntimeError when the provider or profile couldn't be found
+    """
+    # Make sure no path elements are present
+    profile = os.path.basename(profile)
+    provider_name = os.path.basename(provider_name)
+    if not profile:
+        raise ValueError("Profile name cannot be empty!")
+    if not provider_name:
+        raise ValueError("Provider name cannot be empty!")
+
+    directory = os.path.join(ucfg["settings_dir"], provider_name)
+    # create the settings directory if it doesn't exist
+    os.makedirs(directory, exist_ok=True)
+
+    path = os.path.join(directory, f"{profile}.toml")
+    if exists and not os.path.isfile(path):
+        raise RuntimeError(f'Couldn\'t find profile "{profile}"!')
+
+    return os.path.abspath(path)
+
+
[docs]def resolve_provider(ucfg, provider_name): + """Get information about the specified provider as defined in that + provider's `provider.toml`, including the provider's display name and expected + settings. + + At a minimum, each setting has a display name (that likely differs from its + snake_case name) and a type. Currently, there are two types of settings: + string and boolean. String settings can optionally have a "placeholder" + value for use on the front end and a "regex" for making sure that a value + follows an expected pattern. + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the provider to look for + :type provider_name: str + :raises: RuntimeError when the provider couldn't be found + :returns: the provider + :rtype: dict + """ + # Make sure no path elements are present + provider_name = os.path.basename(provider_name) + path = os.path.join(ucfg["providers_dir"], provider_name, "provider.toml") + try: + with open(path) as provider_file: + provider = toml.load(provider_file) + except OSError as error: + raise RuntimeError(f'Couldn\'t find provider "{provider_name}"!') from error + + return provider
+ + +
[docs]def load_profiles(ucfg, provider_name): + """Return all settings profiles associated with a provider + + :param ucfg: upload config + :type ucfg: object + :param provider_name: name a provider to find profiles for + :type provider_name: str + :returns: a dict of settings dicts, keyed by profile name + :rtype: dict + """ + # Make sure no path elements are present + provider_name = os.path.basename(provider_name) + + def load_path(path): + with open(path) as file: + return toml.load(file) + + def get_name(path): + return os.path.splitext(os.path.basename(path))[0] + + paths = glob(os.path.join(ucfg["settings_dir"], provider_name, "*")) + return {get_name(path): load_path(path) for path in paths}
+ + +
[docs]def resolve_playbook_path(ucfg, provider_name): + """Given a provider's name, return the path to its playbook + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the provider to find the playbook for + :type provider_name: str + :raises: RuntimeError when the provider couldn't be found + :returns: the path to the playbook + :rtype: str + """ + # Make sure no path elements are present + provider_name = os.path.basename(provider_name) + + path = os.path.join(ucfg["providers_dir"], provider_name, "playbook.yaml") + if not os.path.isfile(path): + raise RuntimeError(f'Couldn\'t find playbook for "{provider_name}"!') + return path
+ + +
[docs]def list_providers(ucfg): + """List the names of the available upload providers + + :param ucfg: upload config + :type ucfg: object + :returns: a list of all available provider_names + :rtype: list of str + """ + paths = glob(os.path.join(ucfg["providers_dir"], "*")) + return sorted(os.path.basename(path) for path in paths)
+ + +
[docs]def validate_settings(ucfg, provider_name, settings, image_name=None): + """Raise a ValueError if any settings are invalid + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the provider to validate the settings against + :type provider_name: str + :param settings: the settings to validate + :type settings: dict + :param image_name: optionally check whether an image_name is valid + :type image_name: str + :raises: ValueError when the passed settings are invalid + :raises: RuntimeError when provider_name can't be found + """ + if image_name == "": + raise ValueError("Image name cannot be empty!") + type_map = {"string": str, "boolean": bool} + settings_info = resolve_provider(ucfg, provider_name)["settings-info"] + for key, value in settings.items(): + if key not in settings_info: + raise ValueError(f'Received unexpected setting: "{key}"!') + setting_type = settings_info[key]["type"] + correct_type = type_map[setting_type] + if not isinstance(value, correct_type): + raise ValueError( + f'Expected a {correct_type} for "{key}", received a {type(value)}!' + ) + if setting_type == "string" and "regex" in settings_info[key]: + if not re.match(settings_info[key]["regex"], value): + raise ValueError(f'Value "{value}" is invalid for setting "{key}"!')
+ + +
[docs]def save_settings(ucfg, provider_name, profile, settings): + """Save (and overwrite) settings for a given provider + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the cloud provider, e.g. "azure" + :type provider_name: str + :param profile: the name of the profile to save + :type profile: str != "" + :param settings: settings to save for that provider + :type settings: dict + :raises: ValueError when passed invalid settings or an invalid profile name + """ + path = _get_profile_path(ucfg, provider_name, profile, exists=False) + validate_settings(ucfg, provider_name, settings, image_name=None) + + # touch the TOML file if it doesn't exist + if not os.path.isfile(path): + open(path, "a").close() + + # make sure settings files aren't readable by others, as they will contain + # sensitive credentials + current = stat.S_IMODE(os.lstat(path).st_mode) + os.chmod(path, current & ~stat.S_IROTH) + + with open(path, "w") as settings_file: + toml.dump(settings, settings_file)
+ +
[docs]def load_settings(ucfg, provider_name, profile): + """Load settings for a provider's profile + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the cloud provider, e.g. "azure" + :type provider_name: str + :param profile: the name of the profile to save + :type profile: str != "" + :returns: The profile settings for the selected provider + :rtype: dict + :raises: ValueError when passed invalid settings or an invalid profile name + :raises: RuntimeError when the provider or profile couldn't be found + :raises: ValueError when the passed settings are invalid + + This also calls validate_settings on the loaded settings, potentially + raising an error if the saved settings are invalid. + """ + path = _get_profile_path(ucfg, provider_name, profile) + + with open(path) as file: + settings = toml.load(file) + validate_settings(ucfg, provider_name, settings) + return settings
+ +
[docs]def delete_profile(ucfg, provider_name, profile): + """Delete a provider's profile settings file + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the cloud provider, e.g. "azure" + :type provider_name: str + :param profile: the name of the profile to save + :type profile: str != "" + :raises: ValueError when passed invalid settings or an invalid profile name + :raises: RuntimeError when the provider or profile couldn't be found + """ + path = _get_profile_path(ucfg, provider_name, profile) + + if os.path.exists(path): + os.unlink(path)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/lifted/queue.html b/f33-branch/_modules/lifted/queue.html new file mode 100644 index 00000000..9cbb714b --- /dev/null +++ b/f33-branch/_modules/lifted/queue.html @@ -0,0 +1,468 @@ + + + + + + + + + + + lifted.queue — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for lifted.queue

+#
+# 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/>.
+#
+
+from functools import partial
+from glob import glob
+import logging
+import multiprocessing
+
+# We use a multiprocessing Pool for uploads so that we can cancel them with a
+# simple SIGINT, which should bubble down to subprocesses.
+from multiprocessing import Pool
+
+# multiprocessing.dummy is to threads as multiprocessing is to processes.
+# Since daemonic processes can't have children, we use a thread to monitor the
+# upload pool.
+from multiprocessing.dummy import Process
+
+from operator import attrgetter
+import os
+import stat
+import time
+
+import pylorax.api.toml as toml
+
+from lifted.upload import Upload
+from lifted.providers import resolve_playbook_path, validate_settings
+
+# the maximum number of simultaneous uploads
+SIMULTANEOUS_UPLOADS = 1
+
+log = logging.getLogger("lifted")
+multiprocessing.log_to_stderr().setLevel(logging.INFO)
+
+
+def _get_queue_path(ucfg):
+    path = ucfg["queue_dir"]
+
+    # create the upload_queue directory if it doesn't exist
+    os.makedirs(path, exist_ok=True)
+
+    return path
+
+
+def _get_upload_path(ucfg, uuid, write=False):
+    # Make sure no path elements are present
+    uuid = os.path.basename(uuid)
+
+    path = os.path.join(_get_queue_path(ucfg), f"{uuid}.toml")
+    if write and not os.path.exists(path):
+        open(path, "a").close()
+    if os.path.exists(path):
+        # make sure uploads aren't readable by others, as they will contain
+        # sensitive credentials
+        current = stat.S_IMODE(os.lstat(path).st_mode)
+        os.chmod(path, current & ~stat.S_IROTH)
+    return path
+
+
+def _list_upload_uuids(ucfg):
+    paths = glob(os.path.join(_get_queue_path(ucfg), "*"))
+    return [os.path.splitext(os.path.basename(path))[0] for path in paths]
+
+
+def _write_upload(ucfg, upload):
+    with open(_get_upload_path(ucfg, upload.uuid, write=True), "w") as upload_file:
+        toml.dump(upload.serializable(), upload_file)
+
+
+def _write_callback(ucfg):
+    return partial(_write_upload, ucfg)
+
+
+
[docs]def get_upload(ucfg, uuid, ignore_missing=False, ignore_corrupt=False): + """Get an Upload object by UUID + + :param ucfg: upload config + :type ucfg: object + :param uuid: UUID of the upload to get + :type uuid: str + :param ignore_missing: if True, don't raise a RuntimeError when the specified upload is missing, instead just return None + :type ignore_missing: bool + :param ignore_corrupt: if True, don't raise a RuntimeError when the specified upload could not be deserialized, instead just return None + :type ignore_corrupt: bool + :returns: the upload object or None + :rtype: Upload or None + :raises: RuntimeError + """ + try: + with open(_get_upload_path(ucfg, uuid), "r") as upload_file: + return Upload(**toml.load(upload_file)) + except FileNotFoundError as error: + if not ignore_missing: + raise RuntimeError(f"Could not find upload {uuid}!") from error + except toml.TomlError as error: + if not ignore_corrupt: + raise RuntimeError(f"Could not parse upload {uuid}!") from error
+ + +
[docs]def get_uploads(ucfg, uuids): + """Gets a list of Upload objects from a list of upload UUIDs, ignoring + missing or corrupt uploads + + :param ucfg: upload config + :type ucfg: object + :param uuids: list of upload UUIDs to get + :type uuids: list of str + :returns: a list of the uploads that were successfully deserialized + :rtype: list of Upload + """ + uploads = ( + get_upload(ucfg, uuid, ignore_missing=True, ignore_corrupt=True) + for uuid in uuids + ) + return list(filter(None, uploads))
+ + +
[docs]def get_all_uploads(ucfg): + """Get a list of all stored Upload objects + + :param ucfg: upload config + :type ucfg: object + :returns: a list of all stored upload objects + :rtype: list of Upload + """ + return get_uploads(ucfg, _list_upload_uuids(ucfg))
+ + +
[docs]def create_upload(ucfg, provider_name, image_name, settings): + """Creates a new upload + + :param ucfg: upload config + :type ucfg: object + :param provider_name: the name of the cloud provider to upload to, e.g. "azure" + :type provider_name: str + :param image_name: what to name the image in the cloud + :type image_name: str + :param settings: settings to pass to the upload, specific to the cloud provider + :type settings: dict + :returns: the created upload object + :rtype: Upload + """ + validate_settings(ucfg, provider_name, settings, image_name) + return Upload( + provider_name=provider_name, + playbook_path=resolve_playbook_path(ucfg, provider_name), + image_name=image_name, + settings=settings, + status_callback=_write_callback(ucfg), + )
+ + +
[docs]def ready_upload(ucfg, uuid, image_path): + """Pass an image_path to an upload and mark it ready to execute + + :param ucfg: upload config + :type ucfg: object + :param uuid: the UUID of the upload to mark ready + :type uuid: str + :param image_path: the path of the image to pass to the upload + :type image_path: str + """ + get_upload(ucfg, uuid).ready(image_path, _write_callback(ucfg))
+ + +
[docs]def reset_upload(ucfg, uuid, new_image_name=None, new_settings=None): + """Reset an upload so it can be attempted again + + :param ucfg: upload config + :type ucfg: object + :param uuid: the UUID of the upload to reset + :type uuid: str + :param new_image_name: optionally update the upload's image_name + :type new_image_name: str + :param new_settings: optionally update the upload's settings + :type new_settings: dict + """ + upload = get_upload(ucfg, uuid) + validate_settings( + ucfg, + upload.provider_name, + new_settings or upload.settings, + new_image_name or upload.image_name, + ) + if new_image_name: + upload.image_name = new_image_name + if new_settings: + upload.settings = new_settings + upload.reset(_write_callback(ucfg))
+ + +
[docs]def cancel_upload(ucfg, uuid): + """Cancel an upload + + :param ucfg: the compose config + :type ucfg: ComposerConfig + :param uuid: the UUID of the upload to cancel + :type uuid: str + """ + get_upload(ucfg, uuid).cancel(_write_callback(ucfg))
+ + +
[docs]def delete_upload(ucfg, uuid): + """Delete an upload + + :param ucfg: the compose config + :type ucfg: ComposerConfig + :param uuid: the UUID of the upload to delete + :type uuid: str + """ + upload = get_upload(ucfg, uuid) + if upload and upload.is_cancellable(): + upload.cancel() + os.remove(_get_upload_path(ucfg, uuid))
+ + +
[docs]def start_upload_monitor(ucfg): + """Start a thread that manages the upload queue + + :param ucfg: the compose config + :type ucfg: ComposerConfig + """ + process = Process(target=_monitor, args=(ucfg,)) + process.daemon = True + process.start()
+ + +def _monitor(ucfg): + log.info("Started upload monitor.") + for upload in get_all_uploads(ucfg): + # Set abandoned uploads to FAILED + if upload.status == "RUNNING": + upload.set_status("FAILED", _write_callback(ucfg)) + pool = Pool(processes=SIMULTANEOUS_UPLOADS) + pool_uuids = set() + + def remover(uuid): + return lambda _: pool_uuids.remove(uuid) + + while True: + # Every second, scoop up READY uploads from the filesystem and throw + # them in the pool + all_uploads = get_all_uploads(ucfg) + for upload in sorted(all_uploads, key=attrgetter("creation_time")): + ready = upload.status == "READY" + if ready and upload.uuid not in pool_uuids: + log.info("Starting upload %s...", upload.uuid) + pool_uuids.add(upload.uuid) + callback = remover(upload.uuid) + pool.apply_async( + upload.execute, + (_write_callback(ucfg),), + callback=callback, + error_callback=callback, + ) + time.sleep(1) +
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/lifted/upload.html b/f33-branch/_modules/lifted/upload.html new file mode 100644 index 00000000..dff99e84 --- /dev/null +++ b/f33-branch/_modules/lifted/upload.html @@ -0,0 +1,411 @@ + + + + + + + + + + + lifted.upload — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for lifted.upload

+#
+# 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/>.
+#
+
+from datetime import datetime
+import logging
+from multiprocessing import current_process
+import os
+import signal
+from uuid import uuid4
+
+from ansible_runner.interface import run as ansible_run
+from ansible_runner.exceptions import AnsibleRunnerException
+
+log = logging.getLogger("lifted")
+
+
+
[docs]class Upload: + """Represents an upload of an image to a cloud provider. Instances of this + class are serialized as TOML and stored in the upload queue directory, + which is /var/lib/lorax/upload/queue/ by default""" + + def __init__( + self, + uuid=None, + provider_name=None, + playbook_path=None, + image_name=None, + settings=None, + creation_time=None, + upload_log=None, + upload_pid=None, + image_path=None, + status_callback=None, + status=None, + ): + self.uuid = uuid or str(uuid4()) + self.provider_name = provider_name + self.playbook_path = playbook_path + self.image_name = image_name + self.settings = settings + self.creation_time = creation_time or datetime.now().timestamp() + self.upload_log = upload_log or "" + self.upload_pid = upload_pid + self.image_path = image_path + if status: + self.status = status + else: + self.set_status("WAITING", status_callback) + + def _log(self, message, callback=None): + """Logs something to the upload log with an optional callback + + :param message: the object to log + :type message: object + :param callback: a function of the form callback(self) + :type callback: function + """ + if message: + messages = str(message).splitlines() + + # Log multi-line messages as individual log lines + for m in messages: + log.info(m) + self.upload_log += f"{message}\n" + if callback: + callback(self) + +
[docs] def serializable(self): + """Returns a representation of the object as a dict for serialization + + :returns: the object's __dict__ + :rtype: dict + """ + return self.__dict__
+ +
[docs] def summary(self): + """Return a dict with useful information about the upload + + :returns: upload information + :rtype: dict + """ + + return { + "uuid": self.uuid, + "status": self.status, + "provider_name": self.provider_name, + "image_name": self.image_name, + "image_path": self.image_path, + "creation_time": self.creation_time, + "settings": self.settings, + }
+ +
[docs] def set_status(self, status, status_callback=None): + """Sets the status of the upload with an optional callback + + :param status: the new status + :type status: str + :param status_callback: a function of the form callback(self) + :type status_callback: function + """ + self._log("Setting status to %s" % status) + self.status = status + if status_callback: + status_callback(self)
+ +
[docs] def ready(self, image_path, status_callback): + """Provide an image_path and mark the upload as ready to execute + + :param image_path: path of the image to upload + :type image_path: str + :param status_callback: a function of the form callback(self) + :type status_callback: function + """ + self._log("Setting image_path to %s" % image_path) + self.image_path = image_path + if self.status == "WAITING": + self.set_status("READY", status_callback)
+ +
[docs] def reset(self, status_callback): + """Reset the upload so it can be attempted again + + :param status_callback: a function of the form callback(self) + :type status_callback: function + """ + if self.is_cancellable(): + raise RuntimeError(f"Can't reset, status is {self.status}!") + if not self.image_path: + raise RuntimeError("Can't reset, no image supplied yet!") + # self.error = None + self._log("Resetting state") + self.set_status("READY", status_callback)
+ +
[docs] def is_cancellable(self): + """Is the upload in a cancellable state? + + :returns: whether the upload is cancellable + :rtype: bool + """ + return self.status in ("WAITING", "READY", "RUNNING")
+ +
[docs] def cancel(self, status_callback=None): + """Cancel the upload. Sends a SIGINT to self.upload_pid. + + :param status_callback: a function of the form callback(self) + :type status_callback: function + """ + if not self.is_cancellable(): + raise RuntimeError(f"Can't cancel, status is already {self.status}!") + if self.upload_pid: + os.kill(self.upload_pid, signal.SIGINT) + self.set_status("CANCELLED", status_callback)
+ +
[docs] def execute(self, status_callback=None): + """Execute the upload. Meant to be called from a dedicated process so + that the upload can be cancelled by sending a SIGINT to + self.upload_pid. + + :param status_callback: a function of the form callback(self) + :type status_callback: function + """ + if self.status != "READY": + raise RuntimeError("This upload is not ready!") + + try: + self.upload_pid = current_process().pid + self.set_status("RUNNING", status_callback) + self._log("Executing playbook.yml") + + # NOTE: event_handler doesn't seem to be called for playbook errors + logger = lambda e: self._log(e["stdout"], status_callback) + + runner = ansible_run( + playbook=self.playbook_path, + extravars={ + **self.settings, + "image_name": self.image_name, + "image_path": self.image_path, + }, + event_handler=logger, + verbosity=2, + ) + + # Try logging events and stats -- but they may not exist, so catch the error + try: + for e in runner.events: + self._log("%s" % dir(e), status_callback) + + self._log("%s" % runner.stats, status_callback) + except AnsibleRunnerException: + self._log("%s" % runner.stdout.read(), status_callback) + + if runner.status == "successful": + self.set_status("FINISHED", status_callback) + else: + self.set_status("FAILED", status_callback) + except Exception: + import traceback + log.error(traceback.format_exc(limit=2))
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax.html b/f33-branch/_modules/pylorax.html new file mode 100644 index 00000000..0d590437 --- /dev/null +++ b/f33-branch/_modules/pylorax.html @@ -0,0 +1,657 @@ + + + + + + + + + + + pylorax — Lorax 33.10 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"]
+
+# Used for DNF conf.module_platform_id
+DEFAULT_PLATFORM_ID = "platform:f32"
+
+
[docs]class ArchData(DataHolder): + lib64_arches = ("x86_64", "ppc64le", "s390x", "ia64", "aarch64") + bcj_arch = dict(i386="x86", x86_64="x86", + 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, + skip_branding=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, + skip_branding=skip_branding) + + 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 + rc = rb.create_squashfs_runtime(joinpaths(installroot,runtime), + compression=compression, compressargs=compressargs, + size=size) + else: + # Create an ext4 rootfs.img and compress it with squashfs + rc = rb.create_ext4_runtime(joinpaths(installroot,runtime), + compression=compression, compressargs=compressargs, + size=size) + if rc != 0: + logger.error("rootfs.img creation failed. See program.log") + sys.exit(1) + + 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"] + + 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/f33-branch/_modules/pylorax/api/bisect.html b/f33-branch/_modules/pylorax/api/bisect.html new file mode 100644 index 00000000..fa945218 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/bisect.html @@ -0,0 +1,250 @@ + + + + + + + + + + + pylorax.api.bisect — Lorax 33.10 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/f33-branch/_modules/pylorax/api/checkparams.html b/f33-branch/_modules/pylorax/api/checkparams.html new file mode 100644 index 00000000..d81dcc2b --- /dev/null +++ b/f33-branch/_modules/pylorax/api/checkparams.html @@ -0,0 +1,245 @@ + + + + + + + + + + + pylorax.api.checkparams — Lorax 33.10 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/f33-branch/_modules/pylorax/api/cmdline.html b/f33-branch/_modules/pylorax/api/cmdline.html new file mode 100644 index 00000000..5c677db4 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/cmdline.html @@ -0,0 +1,264 @@ + + + + + + + + + + + pylorax.api.cmdline — Lorax 33.10 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/f33-branch/_modules/pylorax/api/compose.html b/f33-branch/_modules/pylorax/api/compose.html new file mode 100644 index 00000000..42917015 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/compose.html @@ -0,0 +1,1468 @@ + + + + + + + + + + + pylorax.api.compose — Lorax 33.10 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 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
+import pylorax.api.toml as toml
+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, enabled in compose_types(share_dir): + if not enabled: + continue + + # 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, only allow enabled types + type_enabled = dict(compose_types(share_dir)).get(compose_type) + if type_enabled is None: + raise RuntimeError("Invalid compose type (%s), must be one of %s" % (compose_type, [t for t, e in compose_types(share_dir)])) + if not type_enabled: + raise RuntimeError("Compose type '%s' is disabled on this architecture" % compose_type) + + # 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 tuples of the supported output types, and their state + + The output types come from the kickstart names in /usr/share/lorax/composer/\*ks + + If they are disabled on the current arch their state is False. If enabled, it is True. + eg. [("alibaba", False), ("ext4-filesystem", True), ...] + """ + # These are compose types that are not supported on an architecture. eg. hyper-v on s390 + # If it is not listed, it is allowed + disable_map = { + "arm": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + "armhfp": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + "aarch64": ["alibaba", "google", "hyper-v", "vhd", "vmdk"], + "ppc": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + "ppc64": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + "ppc64le": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + "s390": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + "s390x": ["alibaba", "ami", "google", "hyper-v", "vhd", "vmdk"], + } + + all_types = sorted([os.path.basename(ks)[:-3] for ks in glob(joinpaths(share_dir, "composer/*.ks"))]) + arch_disabled = disable_map.get(os.uname().machine, []) + + return [(t, t not in arch_disabled) for t in all_types]
+ +
[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, + "squashfs_only": False, + }, + "liveimg-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, + "squashfs_only": False, + }, + "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", + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + "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, + "squashfs_only": False, + }, + } + 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/f33-branch/_modules/pylorax/api/config.html b/f33-branch/_modules/pylorax/api/config.html new file mode 100644 index 00000000..eaaffe1d --- /dev/null +++ b/f33-branch/_modules/pylorax/api/config.html @@ -0,0 +1,341 @@ + + + + + + + + + + + pylorax.api.config — Lorax 33.10 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 + :returns: Configuration + :rtype: ComposerConfig + """ + 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/f33-branch/_modules/pylorax/api/crossdomain.html b/f33-branch/_modules/pylorax/api/crossdomain.html new file mode 100644 index 00000000..d8f653fe --- /dev/null +++ b/f33-branch/_modules/pylorax/api/crossdomain.html @@ -0,0 +1,264 @@ + + + + + + + + + + + pylorax.api.crossdomain — Lorax 31.7 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/f33-branch/_modules/pylorax/api/dnfbase.html b/f33-branch/_modules/pylorax/api/dnfbase.html new file mode 100644 index 00000000..5fa6b8f0 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/dnfbase.html @@ -0,0 +1,387 @@ + + + + + + + + + + + pylorax.api.dnfbase — Lorax 33.10 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 + + # If the system repos are enabled read the dnf vars from /etc/dnf/vars/ + if not conf.has_option("repos", "use_system_repos") or conf.getboolean("repos", "use_system_repos"): + dbc.substitutions.update_from_etc("/") + log.info("dnf vars: %s", dbc.substitutions) + + _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/f33-branch/_modules/pylorax/api/flask_blueprint.html b/f33-branch/_modules/pylorax/api/flask_blueprint.html new file mode 100644 index 00000000..269f9f95 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/flask_blueprint.html @@ -0,0 +1,255 @@ + + + + + + + + + + + pylorax.api.flask_blueprint — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.flask_blueprint

+#
+# 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/>.
+#
+""" Flask Blueprints that support skipping routes
+
+When using Blueprints for API versioning you will usually want to fall back
+to the previous version's rules for routes that have no new behavior. To do
+this we add a 'skip_rule' list to the Blueprint's options dictionary. It lists
+all of the routes that you do not want to register.
+
+For example:
+    from pylorax.api.v0 import v0
+    from pylorax.api.v1 import v1
+
+    server.register_blueprint(v0, url_prefix="/api/v0/")
+    server.register_blueprint(v0, url_prefix="/api/v1/", skip_rules=["/blueprints/list"]
+    server.register_blueprint(v1, url_prefix="/api/v1/")
+
+This will register all of v0's routes under `/api/v0`, and all but `/blueprints/list` under /api/v1,
+and then register v1's version of `/blueprints/list` under `/api/v1`
+
+"""
+from flask import Blueprint
+from flask.blueprints import BlueprintSetupState
+
+
[docs]class BlueprintSetupStateSkip(BlueprintSetupState): + def __init__(self, blueprint, app, options, first_registration, skip_rules): + self._skip_rules = skip_rules + super(BlueprintSetupStateSkip, self).__init__(blueprint, app, options, first_registration) + +
[docs] def add_url_rule(self, rule, endpoint=None, view_func=None, **options): + if rule not in self._skip_rules: + super(BlueprintSetupStateSkip, self).add_url_rule(rule, endpoint, view_func, **options)
+ +
[docs]class BlueprintSkip(Blueprint): + def __init__(self, *args, **kwargs): + super(BlueprintSkip, self).__init__(*args, **kwargs) + +
[docs] def make_setup_state(self, app, options, first_registration=False): + skip_rules = options.pop("skip_rules", []) + return BlueprintSetupStateSkip(self, app, options, first_registration, skip_rules)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/gitrpm.html b/f33-branch/_modules/pylorax/api/gitrpm.html new file mode 100644 index 00000000..ff0bc5a2 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/gitrpm.html @@ -0,0 +1,423 @@ + + + + + + + + + + + pylorax.api.gitrpm — Lorax 33.10 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, stderr=subprocess.STDOUT) + 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, stderr=subprocess.STDOUT) + except subprocess.CalledProcessError as e: + log.error("Failed to archive %s: %s", self._gitRepo["repo"], e.output) + raise RuntimeError('Failed to archive %s from ref "%s"' % (self._gitRepo["repo"], + self._gitRepo["ref"])) + 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, stderr=subprocess.STDOUT) + 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/f33-branch/_modules/pylorax/api/projects.html b/f33-branch/_modules/pylorax/api/projects.html new file mode 100644 index 00000000..346fe545 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/projects.html @@ -0,0 +1,898 @@ + + + + + + + + + + + pylorax.api.projects — Lorax 33.10 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
+from pylorax.sysutils import joinpaths
+
+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) + + if repo.skip_if_unavailable: + repo_str += "skip_if_unavailable=1\n" + + return repo_str
+ +
[docs]def repo_to_source(repo, system_source, api=1): + """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 + :param api: Select which api version of the dict to return (default 1) + :type api: int + :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" + ], + "id": "fedora", + "name": "Fedora $releasever - $basearch", + "proxy": "http://proxy.brianlane.com:8123", + "system": true + "type": "yum-metalink", + "url": "https://mirrors.fedoraproject.org/metalink?repo=fedora-28&arch=x86_64" + } + + The ``name`` field has changed in v1 of the API. + In v0 of the API ``name`` is the repo.id, in v1 it is the repo.name and a new field, + ``id`` has been added for the repo.id + + """ + if api==0: + source = {"name": repo.id, "system": system_source} + else: + source = {"id": repo.id, "name": repo.name, "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_repodict(source): + """Return a tuple suitable for use with dnf.add_new_repo + + :param source: A Weldr source dict + :type source: dict + :returns: A tuple of dnf.Repo attributes + :rtype: (str, list, dict) + + Return a tuple with (id, baseurl|(), kwargs) that can be used + with dnf.repos.add_new_repo + """ + kwargs = {} + if "id" in source: + # This is an API v1 source definition + repoid = source["id"] + if "name" in source: + kwargs["name"] = source["name"] + else: + repoid = source["name"] + + # This will allow errors to be raised so we can catch them + # without this they are logged, but the repo is silently disabled + kwargs["skip_if_unavailable"] = False + + if source["type"] == "yum-baseurl": + baseurl = [source["url"]] + elif source["type"] == "yum-metalink": + kwargs["metalink"] = source["url"] + baseurl = () + elif source["type"] == "yum-mirrorlist": + kwargs["mirrorlist"] = source["url"] + baseurl = () + + if "proxy" in source: + kwargs["proxy"] = source["proxy"] + + if source["check_ssl"]: + kwargs["sslverify"] = True + else: + kwargs["sslverify"] = False + + if source["check_gpg"]: + kwargs["gpgcheck"] = True + else: + kwargs["gpgcheck"] = False + + if "gpgkey_urls" in source: + kwargs["gpgkey"] = tuple(source["gpgkey_urls"]) + + return (repoid, baseurl, kwargs)
+ + +
[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 + :param dnf_conf: The dnf Config object + :type dnf_conf: dnf.conf + :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" + ], + "id": "fedora", + "name": "Fedora $releasever - $basearch", + "proxy": "http://proxy.brianlane.com:8123", + "system": True + "type": "yum-metalink", + "url": "https://mirrors.fedoraproject.org/metalink?repo=fedora-28&arch=x86_64" + } + + If the ``id`` field is included it is used for the repo id, otherwise ``name`` is used. + v0 of the API only used ``name``, v1 added the distinction between ``id`` and ``name``. + """ + repoid, baseurl, kwargs = source_to_repodict(source) + repo = dnf.repo.Repo(repoid, dnf_conf) + if baseurl: + repo.baseurl = baseurl + + # Apply the rest of the kwargs to the Repo object + for k, v in kwargs.items(): + setattr(repo, k, v) + + 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_id): + """Delete a source from a repo file + + :param source_glob: A glob of the repo sources to search + :type source_glob: str + :param source_id: The repo id to delete + :type source_id: 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_id isn't passed to it. + """ + found = False + for f in glob(source_glob): + try: + cfg = ConfigParser() + cfg.read(f) + if source_id in cfg.sections(): + found = True + cfg.remove_section(source_id) + # 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_id, str(e))) + if not found: + raise ProjectsError("source %s not found" % source_id)
+ +
[docs]def new_repo_source(dbo, repoid, source, repo_dir): + """Add a new repo source from a Weldr source dict + + :param dbo: dnf base object + :type dbo: dnf.Base + :param id: The repo id (API v0 uses the name, v1 uses the id) + :type id: str + :param source: A Weldr source dict + :type source: dict + :returns: None + :raises: ... + + Make sure access to the dbo has been locked before calling this. + The `id` parameter will the the 'name' field for API v0, and the 'id' field for API v1 + + DNF variables will be substituted at load time, and on restart. + """ + try: + # Remove it from the RepoDict (NOTE that this isn't explicitly supported by the DNF API) + # 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 repoid in repos: + del dbo.repos[repoid] + + # Add the repo and substitute any dnf variables + _, baseurl, kwargs = source_to_repodict(source) + log.debug("repoid=%s, baseurl=%s, kwargs=%s", repoid, baseurl, kwargs) + r = dbo.repos.add_new_repo(repoid, dbo.conf, baseurl, **kwargs) + r.enable() + + log.info("Updating repository metadata after adding %s", repoid) + dbo.fill_sack(load_system_repo=False) + dbo.read_comps() + + # Remove any previous sources with this id, ignore it if it isn't found + try: + delete_repo_source(joinpaths(repo_dir, "*.repo"), repoid) + except ProjectsError: + pass + + # Make sure the source id can't contain a path traversal by taking the basename + source_path = joinpaths(repo_dir, os.path.basename("%s.repo" % repoid)) + # Write the un-substituted version of the repo to disk + with open(source_path, "w") as f: + repo = source_to_repo(source, dbo.conf) + f.write(dnf_repo_to_file_repo(repo)) + except Exception as e: + log.error("(new_repo_source) adding %s failed: %s", repoid, 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 repoid in repos: + del dbo.repos[repoid] + + log.info("Updating repository metadata after adding %s failed", repoid) + dbo.fill_sack(load_system_repo=False) + dbo.read_comps() + + raise
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/queue.html b/f33-branch/_modules/pylorax/api/queue.html new file mode 100644 index 00000000..df792163 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/queue.html @@ -0,0 +1,1064 @@ + + + + + + + + + + + pylorax.api.queue — Lorax 33.10 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")
+program_log = logging.getLogger("program")
+dnf_log = logging.getLogger("dnf")
+
+import os
+import grp
+from glob import glob
+import multiprocessing as mp
+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
+import pylorax.api.toml as toml
+from pylorax.base import DataHolder
+from pylorax.creator import run_creator
+from pylorax.sysutils import joinpaths, read_tail
+
+from lifted.queue import create_upload, get_uploads, ready_upload, delete_upload
+
+
[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(cfg=cfg, 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 + + # The anaconda logs are also copied into ./anaconda/ in this directory + os.makedirs(joinpaths(dst, "logs"), exist_ok=True) + + def open_handler(loggers, file_name): + handler = logging.FileHandler(joinpaths(dst, "logs", file_name)) + handler.setLevel(logging.DEBUG) + handler.setFormatter(logging.Formatter("%(asctime)s %(levelname)s: %(message)s")) + for logger in loggers: + logger.addHandler(handler) + return (handler, loggers) + + loggers = (((log, program_log, dnf_log), "combined.log"), + ((log,), "composer.log"), + ((program_log,), "program.log"), + ((dnf_log,), "dnf.log")) + handlers = [open_handler(loggers, file_name) for loggers, file_name in loggers] + + 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) + + upload_cfg = cfg.cfg["upload"] + for upload in get_uploads(upload_cfg, uuid_get_uploads(cfg.cfg, uuids[0])): + log.info("Readying upload %s", upload.uuid) + uuid_ready_upload(cfg.cfg, uuids[0], upload.uuid) + 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) + finally: + for handler, loggers in handlers: + for logger in loggers: + logger.removeHandler(handler) + handler.close() + + 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) + + # 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 + # Use default args for dracut + cfg_dict["dracut_conf"] = None + cfg_dict["dracut_args"] = None + + # 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(cfg, results_dir, api=1): + """Return details about the build. + + :param cfg: Configuration settings (required for api=1) + :type cfg: ComposerConfig + :param results_dir: The directory containing the metadata and results for the build + :type results_dir: str + :param api: Select which api version of the dict to return (default 1) + :type api: int + :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. + * uploads - For API v1 details about uploading the image are included + + 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) + + detail = {"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, + } + + if api == 1: + # Get uploads for this build_id + upload_uuids = uuid_get_uploads(cfg, build_id) + summaries = [upload.summary() for upload in get_uploads(cfg["upload"], upload_uuids)] + detail["uploads"] = summaries + return detail
+ +
[docs]def queue_status(cfg, api=1): + """Return details about what is in the queue. + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param api: Select which api version of the dict to return (default 1) + :type api: int + :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(cfg, n, api) + except IOError: + continue + new_details.append(d) + + run_details = [] + for r in run_queue: + try: + d = compose_detail(cfg, r, api) + except IOError: + continue + run_details.append(d) + + return { + "new": new_details, + "run": run_details + }
+ +
[docs]def uuid_status(cfg, uuid, api=1): + """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 + :param api: Select which api version of the dict to return (default 1) + :type api: int + :returns: Details about the build + :rtype: dict or None + + Returns the same dict as `compose_detail()` + """ + uuid_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + try: + return compose_detail(cfg, uuid_dir, api) + except IOError: + return None
+ +
[docs]def build_status(cfg, status_filter=None, api=1): + """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 + :param api: Select which api version of the dict to return (default 1) + :type api: int + :returns: A list of the build details (from compose_detail) + :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(cfg, build, api)) + except IOError: + pass + return results
+ +def _upload_list_path(cfg, uuid): + """Return the path to the UPLOADS file + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: Path to the UPLOADS file listing the build's associated uploads + :rtype: str + :raises: RuntimeError if the uuid is not found + """ + results_dir = joinpaths(cfg.get("composer", "lib_dir"), "results", uuid) + if not os.path.isdir(results_dir): + raise RuntimeError(f'"{uuid}" is not a valid build uuid!') + return joinpaths(results_dir, "UPLOADS") + +
[docs]def uuid_schedule_upload(cfg, uuid, provider_name, image_name, settings): + """Schedule an upload of an image + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :param provider_name: The name of the cloud provider, e.g. "azure" + :type provider_name: str + :param image_name: Path of the image to upload + :type image_name: str + :param settings: Settings to use for the selected provider + :type settings: dict + :returns: uuid of the upload + :rtype: str + :raises: RuntimeError if the uuid is not a valid build uuid + """ + status = uuid_status(cfg, uuid) + if status is None: + raise RuntimeError(f'"{uuid}" is not a valid build uuid!') + + upload = create_upload(cfg["upload"], provider_name, image_name, settings) + uuid_add_upload(cfg, uuid, upload.uuid) + return upload.uuid
+ +
[docs]def uuid_get_uploads(cfg, uuid): + """Return the list of uploads for a build uuid + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :returns: The upload UUIDs associated with the build UUID + :rtype: frozenset + """ + try: + with open(_upload_list_path(cfg, uuid)) as uploads_file: + return frozenset(uploads_file.read().split()) + except FileNotFoundError: + return frozenset()
+ +
[docs]def uuid_add_upload(cfg, uuid, upload_uuid): + """Add an upload UUID to a build + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :param upload_uuid: The UUID of the upload + :type upload_uuid: str + :returns: None + :rtype: None + """ + if upload_uuid not in uuid_get_uploads(cfg, uuid): + with open(_upload_list_path(cfg, uuid), "a") as uploads_file: + print(upload_uuid, file=uploads_file) + status = uuid_status(cfg, uuid) + if status and status["queue_status"] == "FINISHED": + uuid_ready_upload(cfg, uuid, upload_uuid)
+ +
[docs]def uuid_remove_upload(cfg, upload_uuid): + """Remove an upload UUID from the build + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param upload_uuid: The UUID of the upload + :type upload_uuid: str + :returns: None + :rtype: None + :raises: RuntimeError if the upload_uuid is not found + """ + for build_uuid in (os.path.basename(b) for b in glob(joinpaths(cfg.get("composer", "lib_dir"), "results/*"))): + uploads = uuid_get_uploads(cfg, build_uuid) + if upload_uuid not in uploads: + continue + + uploads = uploads - frozenset((upload_uuid,)) + with open(_upload_list_path(cfg, build_uuid), "w") as uploads_file: + for upload in uploads: + print(upload, file=uploads_file) + return + + raise RuntimeError(f"{upload_uuid} is not a valid upload id!")
+ +
[docs]def uuid_ready_upload(cfg, uuid, upload_uuid): + """Set an upload to READY if the build is in FINISHED state + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :param upload_uuid: The UUID of the upload + :type upload_uuid: str + :returns: None + :rtype: None + :raises: RuntimeError if the build uuid is invalid or not in FINISHED state. + """ + status = uuid_status(cfg, uuid) + if not status: + raise RuntimeError(f"{uuid} is not a valid build id!") + if status["queue_status"] != "FINISHED": + raise RuntimeError(f"Build {uuid} is not finished!") + _, image_path = uuid_image(cfg, uuid) + ready_upload(cfg["upload"], upload_uuid, image_path)
+ +
[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) + + for upload in get_uploads(cfg["upload"], uuid_get_uploads(cfg, uuid)): + delete_upload(cfg["upload"], upload.uuid) + + shutil.rmtree(uuid_dir) + return True
+ +
[docs]def uuid_info(cfg, uuid, api=1): + """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(cfg, uuid_dir, api) + + 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() + + info = {"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"], + } + if api == 1: + upload_uuids = uuid_get_uploads(cfg, uuid) + summaries = [upload.summary() for upload in get_uploads(cfg["upload"], upload_uuids)] + info["uploads"] = summaries + return info
+ +
[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` KiB from the end of the most currently relevant log for a + given compose + + :param cfg: Configuration settings + :type cfg: ComposerConfig + :param uuid: The UUID of the build + :type uuid: str + :param size: Number of KiB to read. Default is 1024 + :type size: int + :returns: Up to `size` KiB from the end of the log + :rtype: str + :raises: RuntimeError if there was a problem (eg. no log file available) + + This function will return the end of either the anaconda log, the packaging + log, or the combined composer logs, depending on the progress of the + compose. It tries to return lines from the end of the log, it will attempt + to start on a line boundary, and it 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) + + def get_log_path(): + # Try to return the most relevant log at any given time during the + # compose. If the compose is not running, return the composer log. + anaconda_log = "/tmp/anaconda.log" + packaging_log = "/tmp/packaging.log" + combined_log = joinpaths(uuid_dir, "logs", "combined.log") + if status["queue_status"] != "RUNNING" or not os.path.isfile(anaconda_log): + return combined_log + if not os.path.isfile(packaging_log): + return anaconda_log + try: + anaconda_mtime = os.stat(anaconda_log).st_mtime + packaging_mtime = os.stat(packaging_log).st_mtime + # If the packaging log exists and its last message is at least 15 + # seconds newer than the anaconda log, return the packaging log. + if packaging_mtime > anaconda_mtime + 15: + return packaging_log + return anaconda_log + except OSError: + # Return the combined log if anaconda_log or packaging_log disappear + return combined_log + try: + tail = read_tail(get_log_path(), size) + except OSError as e: + raise RuntimeError("No log available.") from e + return tail
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/recipes.html b/f33-branch/_modules/pylorax/api/recipes.html new file mode 100644 index 00000000..5f9bb7db --- /dev/null +++ b/f33-branch/_modules/pylorax/api/recipes.html @@ -0,0 +1,1477 @@ + + + + + + + + + + + pylorax.api.recipes — Lorax 33.10 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 semantic_version as semver
+
+from pylorax.api.projects import dep_evra
+from pylorax.base import DataHolder
+from pylorax.sysutils import joinpaths
+import pylorax.api.toml as toml
+
+
+
[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 check_required_list(lst, fields): + """Check a list of dicts for required fields + + :param lst: A list of dicts with fields + :type lst: list of dict + :param fields: A list of field name strings + :type fields: list of str + :returns: A list of error strings + :rtype: list of str + """ + errors = [] + for i, m in enumerate(lst): + m_errs = [] + errors.extend(check_list_case(fields, m.keys(), prefix="%d " % (i+1))) + for f in fields: + if f not in m: + m_errs.append("'%s'" % f) + if m_errs: + errors.append("%d is missing %s" % (i+1, ", ".join(m_errs))) + return errors
+ +
[docs]def check_list_case(expected_keys, recipe_keys, prefix=""): + """Check the case of the recipe keys + + :param expected_keys: A list of expected key strings + :type expected_keys: list of str + :param recipe_keys: A list of the recipe's key strings + :type recipe_keys: list of str + :returns: list of errors + :rtype: list of str + """ + errors = [] + for k in recipe_keys: + if k in expected_keys: + continue + if k.lower() in expected_keys: + errors.append(prefix + "%s should be %s" % (k, k.lower())) + return errors
+ +
[docs]def check_recipe_dict(recipe_dict): + """Check a dict before using it to create a new Recipe + + :param recipe_dict: A plain dict of the recipe + :type recipe_dict: dict + :returns: True if dict is ok + :rtype: bool + :raises: RecipeError + + This checks a dict to make sure required fields are present, + that optional fields are correct, and that other optional fields + are of the correct format, when included. + + This collects all of the errors and returns a single RecipeError with + a string that can be presented to users. + """ + errors = [] + + # Check for wrong case of top level keys + top_keys = ["name", "description", "version", "modules", "packages", "groups", "repos", "customizations"] + errors.extend(check_list_case(recipe_dict.keys(), top_keys)) + + if "name" not in recipe_dict: + errors.append("Missing 'name'") + if "description" not in recipe_dict: + errors.append("Missing 'description'") + if "version" in recipe_dict: + try: + semver.Version(recipe_dict["version"]) + except ValueError: + errors.append("Invalid 'version', must use Semantic Versioning") + + # Examine all the modules + if recipe_dict.get("modules"): + module_errors = check_required_list(recipe_dict["modules"], ["name", "version"]) + if module_errors: + errors.append("'modules' errors:\n%s" % "\n".join(module_errors)) + + # Examine all the packages + if recipe_dict.get("packages"): + package_errors = check_required_list(recipe_dict["packages"], ["name", "version"]) + if package_errors: + errors.append("'packages' errors:\n%s" % "\n".join(package_errors)) + + if recipe_dict.get("groups"): + groups_errors = check_required_list(recipe_dict["groups"], ["name"]) + if groups_errors: + errors.append("'groups' errors:\n%s" % "\n".join(groups_errors)) + + if recipe_dict.get("repos") and recipe_dict.get("repos").get("git"): + repos_errors = check_required_list(recipe_dict.get("repos").get("git"), + ["rpmname", "rpmversion", "rpmrelease", "summary", "repo", "ref", "destination"]) + if repos_errors: + errors.append("'repos.git' errors:\n%s" % "\n".join(repos_errors)) + + # No customizations to check, exit now + c = recipe_dict.get("customizations") + if not c: + return errors + + # Make sure to catch empty sections by testing for keywords, not just looking at .get() result. + if "kernel" in c: + errors.extend(check_list_case(["append"], c["kernel"].keys(), prefix="kernel ")) + if "append" not in c.get("kernel", []): + errors.append("'customizations.kernel': missing append field.") + + if "sshkey" in c: + sshkey_errors = check_required_list(c.get("sshkey"), ["user", "key"]) + if sshkey_errors: + errors.append("'customizations.sshkey' errors:\n%s" % "\n".join(sshkey_errors)) + + if "user" in c: + user_errors = check_required_list(c.get("user"), ["name"]) + if user_errors: + errors.append("'customizations.user' errors:\n%s" % "\n".join(user_errors)) + + if "group" in c: + group_errors = check_required_list(c.get("group"), ["name"]) + if group_errors: + errors.append("'customizations.group' errors:\n%s" % "\n".join(group_errors)) + + if "timezone" in c: + errors.extend(check_list_case(["timezone", "ntpservers"], c["timezone"].keys(), prefix="timezone ")) + if not c.get("timezone"): + errors.append("'customizations.timezone': missing timezone or ntpservers fields.") + + if "locale" in c: + errors.extend(check_list_case(["languages", "keyboard"], c["locale"].keys(), prefix="locale ")) + if not c.get("locale"): + errors.append("'customizations.locale': missing languages or keyboard fields.") + + if "firewall" in c: + errors.extend(check_list_case(["ports"], c["firewall"].keys(), prefix="firewall ")) + if not c.get("firewall"): + errors.append("'customizations.firewall': missing ports field or services section.") + + if "services" in c.get("firewall", []): + errors.extend(check_list_case(["enabled", "disabled"], c["firewall"]["services"].keys(), prefix="firewall.services ")) + if not c.get("firewall").get("services"): + errors.append("'customizations.firewall.services': missing enabled or disabled fields.") + + if "services" in c: + errors.extend(check_list_case(["enabled", "disabled"], c["services"].keys(), prefix="services ")) + if not c.get("services"): + errors.append("'customizations.services': missing enabled or disabled fields.") + + return errors
+ +
[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 + """ + errors = check_recipe_dict(recipe_dict) + if errors: + msg = "\n".join(errors) + raise RecipeError(msg) + + # 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 (RecipeError, 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() + time_str = datetime.format_iso8601() + if not time_str: + raise CommitTimeValError + + 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_field_value(field, value, lst): + """Find a field matching value in the list of dicts. + + :param field: field to search for + :type field: str + :param value: value to match in the field + :type value: str + :param lst: List of dict's with field + :type lst: list of dict + :returns: First dict with matching field:value, or None + :rtype: dict or None + + Used to return a specific entry from a list that looks like this: + + [{"name": "one", "attr": "green"}, ...] + + find_field_value("name", "one", lst) will return the matching dict. + """ + for d in lst: + if d.get(field) and d.get(field) == value: + return d + return None
+ +
[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 + :type lst: list of dict + :returns: First dict with matching name, or None + :rtype: dict or None + + This is just a wrapper for find_field_value with field set to "name" + """ + return find_field_value("name", name, lst)
+ +
[docs]def find_recipe_obj(path, recipe, default=None): + """Find a recipe object + + :param path: A list of dict field names + :type path: list of str + :param recipe: The recipe to search + :type recipe: Recipe + :param default: The value to return if it is not found + :type default: Any + + Return the object found by applying the path to the dicts in the recipe, or + return the default if it doesn't exist. + + eg. {"customizations": {"hostname": "foo", "users": [...]}} + + find_recipe_obj(["customizations", "hostname"], recipe, "") + """ + o = recipe + try: + for p in path: + if not o.get(p): + return default + o = o.get(p) + except AttributeError: + return default + + return o
+ +
[docs]def diff_lists(title, field, old_items, new_items): + """Return the differences between two lists of dicts. + + :param title: Title of the entry + :type title: str + :param field: Field to use as the key for comparisons + :type field: 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_fields= set(m[field] for m in old_items) + new_fields= set(m[field] for m in new_items) + + added_items = new_fields.difference(old_fields) + added_items = sorted(added_items, key=lambda n: n.lower()) + + removed_items = old_fields.difference(new_fields) + removed_items = sorted(removed_items, key=lambda n: n.lower()) + + same_items = old_fields.intersection(new_fields) + same_items = sorted(same_items, key=lambda n: n.lower()) + + for v in added_items: + diffs.append({"old":None, + "new":{title:find_field_value(field, v, new_items)}}) + + for v in removed_items: + diffs.append({"old":{title:find_field_value(field, v, old_items)}, + "new":None}) + + for v in same_items: + old_item = find_field_value(field, v, old_items) + new_item = find_field_value(field, v, new_items) + if old_item != new_item: + diffs.append({"old":{title:old_item}, + "new":{title:new_item}}) + + return diffs
+ +
[docs]def customizations_diff(old_recipe, new_recipe): + """Diff the customizations sections from two versions of a recipe + """ + diffs = [] + old_keys = set(old_recipe.get("customizations", {}).keys()) + new_keys = set(new_recipe.get("customizations", {}).keys()) + + added_keys = new_keys.difference(old_keys) + added_keys = sorted(added_keys, key=lambda n: n.lower()) + + removed_keys = old_keys.difference(new_keys) + removed_keys = sorted(removed_keys, key=lambda n: n.lower()) + + same_keys = old_keys.intersection(new_keys) + same_keys = sorted(same_keys, key=lambda n: n.lower()) + + for v in added_keys: + diffs.append({"old": None, + "new": {"Customizations."+v: new_recipe["customizations"][v]}}) + + for v in removed_keys: + diffs.append({"old": {"Customizations."+v: old_recipe["customizations"][v]}, + "new": None}) + + for v in same_keys: + if new_recipe["customizations"][v] == old_recipe["customizations"][v]: + continue + + if type(new_recipe["customizations"][v]) == type([]): + # Lists of dicts need to use diff_lists + # sshkey uses 'user', user and group use 'name' + if "user" in new_recipe["customizations"][v][0]: + field_name = "user" + elif "name" in new_recipe["customizations"][v][0]: + field_name = "name" + else: + raise RuntimeError("%s list has unrecognized key, not 'name' or 'user'" % "customizations."+v) + + diffs.extend(diff_lists("Customizations."+v, field_name, old_recipe["customizations"][v], new_recipe["customizations"][v])) + else: + diffs.append({"old": {"Customizations."+v: old_recipe["customizations"][v]}, + "new": {"Customizations."+v: new_recipe["customizations"][v]}}) + + 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]}}) + + # These lists always exist + diffs.extend(diff_lists("Module", "name", old_recipe["modules"], new_recipe["modules"])) + diffs.extend(diff_lists("Package", "name", old_recipe["packages"], new_recipe["packages"])) + diffs.extend(diff_lists("Group", "name", old_recipe["groups"], new_recipe["groups"])) + + # The customizations section can contain a number of different types + diffs.extend(customizations_diff(old_recipe, new_recipe)) + + # repos contains keys that are lists (eg. [[repos.git]]) + diffs.extend(diff_lists("Repos.git", "rpmname", + find_recipe_obj(["repos", "git"], old_recipe, []), + find_recipe_obj(["repos", "git"], new_recipe, []))) + + 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/f33-branch/_modules/pylorax/api/server.html b/f33-branch/_modules/pylorax/api/server.html new file mode 100644 index 00000000..f71cf1b8 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/server.html @@ -0,0 +1,304 @@ + + + + + + + + + + + pylorax.api.server — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.server

+#
+# 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 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
+import werkzeug
+
+from pylorax import vernum
+from pylorax.api.errors import HTTP_ERROR
+from pylorax.api.v0 import v0_api
+from pylorax.api.v1 import v1_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")
+def api_status():
+    """
+    `/api/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="1",
+                   db_version="0",
+                   schema_version="0",
+                   db_supported=True,
+                   msgs=server.config["TEMPLATE_ERRORS"])
+
+@server.errorhandler(werkzeug.exceptions.HTTPException)
+def bad_request(error):
+    return jsonify(status=False, errors=[{ "id": HTTP_ERROR, "code": error.code, "msg": error.name }]), error.code
+
+# Register the v0 API on /api/v0/
+server.register_blueprint(v0_api, url_prefix="/api/v0/")
+
+# Register the v1 API on /api/v1/
+# Use v0 routes by default
+skip_rules = [
+    "/compose",
+    "/compose/queue",
+    "/compose/finished",
+    "/compose/failed",
+    "/compose/status/<uuids>",
+    "/compose/info/<uuid>",
+    "/projects/source/info/<source_names>",
+    "/projects/source/new",
+]
+server.register_blueprint(v0_api, url_prefix="/api/v1/", skip_rules=skip_rules)
+server.register_blueprint(v1_api, url_prefix="/api/v1/")
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/timestamp.html b/f33-branch/_modules/pylorax/api/timestamp.html new file mode 100644 index 00000000..2d035d26 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/timestamp.html @@ -0,0 +1,252 @@ + + + + + + + + + + + pylorax.api.timestamp — Lorax 33.10 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 time
+
+from pylorax.sysutils import joinpaths
+import pylorax.api.toml as toml
+
+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/f33-branch/_modules/pylorax/api/toml.html b/f33-branch/_modules/pylorax/api/toml.html new file mode 100644 index 00000000..b41b7c7e --- /dev/null +++ b/f33-branch/_modules/pylorax/api/toml.html @@ -0,0 +1,243 @@ + + + + + + + + + + + pylorax.api.toml — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.toml

+#
+# 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/>.
+#
+
+import toml
+
+
[docs]class TomlError(toml.TomlDecodeError): + pass
+ +
[docs]def loads(s): + if isinstance(s, bytes): + s = s.decode('utf-8') + try: + return toml.loads(s) + except toml.TomlDecodeError as e: + raise TomlError(e.msg, e.doc, e.pos)
+ +
[docs]def dumps(o): + # strip the result, because `toml.dumps` adds a lot of newlines + return toml.dumps(o, encoder=toml.TomlEncoder(dict)).strip()
+ +
[docs]def load(file): + try: + return toml.load(file) + except toml.TomlDecodeError as e: + raise TomlError(e.msg, e.doc, e.pos)
+ +
[docs]def dump(o, file): + return toml.dump(o, file)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/utils.html b/f33-branch/_modules/pylorax/api/utils.html new file mode 100644 index 00000000..a4cbb4de --- /dev/null +++ b/f33-branch/_modules/pylorax/api/utils.html @@ -0,0 +1,250 @@ + + + + + + + + + + + pylorax.api.utils — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.utils

+#
+# 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/>.
+""" API utility functions
+"""
+from pylorax.api.recipes import RecipeError, RecipeFileError, read_recipe_commit
+
+
[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
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/v0.html b/f33-branch/_modules/pylorax/api/v0.html new file mode 100644 index 00000000..7b6e4512 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/v0.html @@ -0,0 +1,2198 @@ + + + + + + + + + + + pylorax.api.v0 — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.v0

+#
+# 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/>.
+#
+""" 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.
+"""
+
+import logging
+log = logging.getLogger("lorax-composer")
+
+import os
+from flask import jsonify, request, Response, send_file
+from flask import current_app as api
+
+from pylorax.sysutils import joinpaths
+from pylorax.api.checkparams import checkparams
+from pylorax.api.compose import start_build, compose_types
+from pylorax.api.errors import *                               # pylint: disable=wildcard-import,unused-wildcard-import
+from pylorax.api.flask_blueprint import BlueprintSkip
+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, new_repo_source
+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 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, VALID_BLUEPRINT_NAME
+import pylorax.api.toml as toml
+from pylorax.api.utils import take_limits, blueprint_exists
+from pylorax.api.workspace import workspace_read, workspace_write, workspace_delete, workspace_exists
+
+# The API functions don't actually get called by any code here
+# pylint: disable=unused-variable
+
+# Create the v0 routes Blueprint with skip_routes support
+v0_api = BlueprintSkip("v0_routes", __name__)
+
+
[docs]@v0_api.route("/blueprints/list") +def v0_blueprints_list(): + """List the available blueprints on a branch. + + **/api/v0/blueprints/list** + + List the available blueprints:: + + { "limit": 20, + "offset": 0, + "blueprints": [ + "atlas", + "development", + "glusterfs", + "http-server", + "jboss", + "kubernetes" ], + "total": 6 } + """ + 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))
+ +
[docs]@v0_api.route("/blueprints/info", defaults={'blueprint_names': ""}) +@v0_api.route("/blueprints/info/<blueprint_names>") +@checkparams([("blueprint_names", "", "no blueprint names given")]) +def v0_blueprints_info(blueprint_names): + """Return the contents of the blueprint, or a list of blueprints + + **/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 Responses`_. + + 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": [] + } + """ + if any(VALID_BLUEPRINT_NAME.match(blueprint_name) is None for blueprint_name in blueprint_names.split(',')): + 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)
+ +
[docs]@v0_api.route("/blueprints/changes", defaults={'blueprint_names': ""}) +@v0_api.route("/blueprints/changes/<blueprint_names>") +@checkparams([("blueprint_names", "", "no blueprint names given")]) +def v0_blueprints_changes(blueprint_names): + """Return the changes to a blueprint or list of 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 + } + ] + } + """ + if any(VALID_BLUEPRINT_NAME.match(blueprint_name) is None for blueprint_name in blueprint_names.split(',')): + 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)
+ +
[docs]@v0_api.route("/blueprints/new", methods=["POST"]) +def v0_blueprints_new(): + """Commit a new blueprint + + **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. + """ + 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_BLUEPRINT_NAME.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)
+ +
[docs]@v0_api.route("/blueprints/delete", defaults={'blueprint_name': ""}, methods=["DELETE"]) +@v0_api.route("/blueprints/delete/<blueprint_name>", methods=["DELETE"]) +@checkparams([("blueprint_name", "", "no blueprint name given")]) +def v0_blueprints_delete(blueprint_name): + """Delete a blueprint from git + + **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. + """ + if VALID_BLUEPRINT_NAME.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)
+ +
[docs]@v0_api.route("/blueprints/workspace", methods=["POST"]) +def v0_blueprints_workspace(): + """Write a blueprint to the workspace + + **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. + """ + 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_BLUEPRINT_NAME.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)
+ +
[docs]@v0_api.route("/blueprints/workspace", defaults={'blueprint_name': ""}, methods=["DELETE"]) +@v0_api.route("/blueprints/workspace/<blueprint_name>", methods=["DELETE"]) +@checkparams([("blueprint_name", "", "no blueprint name given")]) +def v0_blueprints_delete_workspace(blueprint_name): + """Delete a blueprint from the workspace + + **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. + """ + if VALID_BLUEPRINT_NAME.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: + if not workspace_exists(api.config["GITLOCK"].repo, branch, blueprint_name): + raise Exception("Unknown blueprint: %s" % blueprint_name) + + 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)
+ +
[docs]@v0_api.route("/blueprints/undo", defaults={'blueprint_name': "", 'commit': ""}, methods=["POST"]) +@v0_api.route("/blueprints/undo/<blueprint_name>", defaults={'commit': ""}, methods=["POST"]) +@v0_api.route("/blueprints/undo/<blueprint_name>/<commit>", methods=["POST"]) +@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. + + **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. + """ + if VALID_BLUEPRINT_NAME.match(blueprint_name) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + if VALID_BLUEPRINT_NAME.match(commit) 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)
+ +
[docs]@v0_api.route("/blueprints/tag", defaults={'blueprint_name': ""}, methods=["POST"]) +@v0_api.route("/blueprints/tag/<blueprint_name>", methods=["POST"]) +@checkparams([("blueprint_name", "", "no blueprint name given")]) +def v0_blueprints_tag(blueprint_name): + """Tag a blueprint's latest blueprint commit as a 'revision' + + **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. + """ + if VALID_BLUEPRINT_NAME.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)
+ +
[docs]@v0_api.route("/blueprints/diff", defaults={'blueprint_name': "", 'from_commit': "", 'to_commit': ""}) +@v0_api.route("/blueprints/diff/<blueprint_name>", defaults={'from_commit': "", 'to_commit': ""}) +@v0_api.route("/blueprints/diff/<blueprint_name>/<from_commit>", defaults={'to_commit': ""}) +@v0_api.route("/blueprints/diff/<blueprint_name>/<from_commit>/<to_commit>") +@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 + + **/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 + } + ] + } + """ + 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)
+ +
[docs]@v0_api.route("/blueprints/freeze", defaults={'blueprint_names': ""}) +@v0_api.route("/blueprints/freeze/<blueprint_names>") +@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 + + **/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" + } + } + ] + } + """ + if any(VALID_BLUEPRINT_NAME.match(blueprint_name) is None for blueprint_name in blueprint_names.split(',')): + 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)
+ +
[docs]@v0_api.route("/blueprints/depsolve", defaults={'blueprint_names': ""}) +@v0_api.route("/blueprints/depsolve/<blueprint_names>") +@checkparams([("blueprint_names", "", "no blueprint names given")]) +def v0_blueprints_depsolve(blueprint_names): + """Return the dependencies for a blueprint + + **/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.*" + }, + ... + } + } + ] + } + """ + if any(VALID_BLUEPRINT_NAME.match(blueprint_name) is None for blueprint_name in blueprint_names.split(',')): + 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)
+ +
[docs]@v0_api.route("/projects/list") +def v0_projects_list(): + """List all of the available projects/packages + + **/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 + } + """ + 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))
+ +
[docs]@v0_api.route("/projects/info", defaults={'project_names': ""}) +@v0_api.route("/projects/info/<project_names>") +@checkparams([("project_names", "", "no project names given")]) +def v0_projects_info(project_names): + """Return detailed information about the listed projects + + **/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" + } + ] + } + """ + 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)
+ +
[docs]@v0_api.route("/projects/depsolve", defaults={'project_names': ""}) +@v0_api.route("/projects/depsolve/<project_names>") +@checkparams([("project_names", "", "no project names given")]) +def v0_projects_depsolve(project_names): + """Return detailed information about the listed projects + + **/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" + }, + ... + ] + } + """ + 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)
+ +
[docs]@v0_api.route("/projects/source/list") +def v0_projects_source_list(): + """Return the list of source names + + **/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" + ] + } + """ + 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)
+ +
[docs]@v0_api.route("/projects/source/info", defaults={'source_names': ""}) +@v0_api.route("/projects/source/info/<source_names>") +@checkparams([("source_names", "", "no source names given")]) +def v0_projects_source_info(source_names): + """Return detailed info about the list of sources + + **/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" + } + } + } + """ + 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, api=0) + + 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)
+ +
[docs]@v0_api.route("/projects/source/new", methods=["POST"]) +def v0_projects_source_new(): + """Add a new package source. Or change an existing one + + **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" + ] + } + + + """ + 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: + repo_dir = api.config["COMPOSER_CFG"].get("composer", "repo_dir") + new_repo_source(api.config["DNFLOCK"].dbo, source["name"], source, repo_dir) + except Exception as e: + return jsonify(status=False, errors=[{"id": PROJECTS_ERROR, "msg": str(e)}]), 400 + + return jsonify(status=True)
+ +
[docs]@v0_api.route("/projects/source/delete", defaults={'source_name': ""}, methods=["DELETE"]) +@v0_api.route("/projects/source/delete/<source_name>", methods=["DELETE"]) +@checkparams([("source_name", "", "no source name given")]) +def v0_projects_source_delete(source_name): + """Delete the named source and return a status response + + **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. + """ + 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)
+ +
[docs]@v0_api.route("/modules/list") +@v0_api.route("/modules/list/<module_names>") +def v0_modules_list(module_names=None): + """List available modules, filtering by module_names + + **/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 + } + """ + 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))
+ +
[docs]@v0_api.route("/modules/info", defaults={'module_names': ""}) +@v0_api.route("/modules/info/<module_names>") +@checkparams([("module_names", "", "no module names given")]) +def v0_modules_info(module_names): + """Return detailed information about the listed modules + + **/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" + } + ] + } + """ + 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)
+ +
[docs]@v0_api.route("/compose", methods=["POST"]) +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. + + **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 + } + """ + # 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_BLUEPRINT_NAME.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)
+ +
[docs]@v0_api.route("/compose/types") +def v0_compose_types(): + """Return the list of enabled output types + + (only enabled types are returned) + + **/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" + } + ] + } + """ + share_dir = api.config["COMPOSER_CFG"].get("composer", "share_dir") + return jsonify(types=[{"name": t, "enabled": e} for t, e in compose_types(share_dir)])
+ +
[docs]@v0_api.route("/compose/queue") +def v0_compose_queue(): + """Return the status of the new and running queues + + **/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" + } + ] + } + """ + return jsonify(queue_status(api.config["COMPOSER_CFG"], api=0))
+ +
[docs]@v0_api.route("/compose/finished") +def v0_compose_finished(): + """Return the list of finished composes + + **/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" + } + ] + } + """ + return jsonify(finished=build_status(api.config["COMPOSER_CFG"], "FINISHED", api=0))
+ +
[docs]@v0_api.route("/compose/failed") +def v0_compose_failed(): + """Return the list of failed composes + + **/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" + } + ] + } + """ + return jsonify(failed=build_status(api.config["COMPOSER_CFG"], "FAILED", api=0))
+ +
[docs]@v0_api.route("/compose/status", defaults={'uuids': ""}) +@v0_api.route("/compose/status/<uuids>") +@checkparams([("uuids", "", "no UUIDs given")]) +def v0_compose_status(uuids): + """Return the status of the listed uuids + + **/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" + } + ] + } + """ + 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) + + # Check the arguments for invalid characters + for a in [blueprint, status, compose_type]: + if a is not None and VALID_API_STRING.match(a) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + results = [] + errors = [] + + if uuids.strip() == '*': + queue_status_dict = queue_status(api.config["COMPOSER_CFG"], api=0) + queue_new = queue_status_dict["new"] + queue_running = queue_status_dict["run"] + candidates = queue_new + queue_running + build_status(api.config["COMPOSER_CFG"], api=0) + else: + candidates = [] + for uuid in [n.strip().lower() for n in uuids.split(",")]: + details = uuid_status(api.config["COMPOSER_CFG"], uuid, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/cancel", defaults={'uuid': ""}, methods=["DELETE"]) +@v0_api.route("/compose/cancel/<uuid>", methods=["DELETE"]) +@checkparams([("uuid", "", "no UUID given")]) +def v0_compose_cancel(uuid): + """Cancel a running compose and delete its results directory + + **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" + } + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/delete", defaults={'uuids': ""}, methods=["DELETE"]) +@v0_api.route("/compose/delete/<uuids>", methods=["DELETE"]) +@checkparams([("uuids", "", "no UUIDs given")]) +def v0_compose_delete(uuids): + """Delete the compose results for the listed uuids + + **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" + } + ] + } + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/info", defaults={'uuid': ""}) +@v0_api.route("/compose/info/<uuid>") +@checkparams([("uuid", "", "no UUID given")]) +def v0_compose_info(uuid): + """Return detailed info about a compose + + **/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", + ... + } + } + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/metadata", defaults={'uuid': ""}) +@v0_api.route("/compose/metadata/<uuid>") +@checkparams([("uuid","", "no UUID given")]) +def v0_compose_metadata(uuid): + """Return a tar of the metadata for the build + + **/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. + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/results", defaults={'uuid': ""}) +@v0_api.route("/compose/results/<uuid>") +@checkparams([("uuid","", "no UUID given")]) +def v0_compose_results(uuid): + """Return a tar of the metadata and the results for the build + + **/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 + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/logs", defaults={'uuid': ""}) +@v0_api.route("/compose/logs/<uuid>") +@checkparams([("uuid","", "no UUID given")]) +def v0_compose_logs(uuid): + """Return a tar of the metadata for the build + + **/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 + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/image", defaults={'uuid': ""}) +@v0_api.route("/compose/image/<uuid>") +@checkparams([("uuid","", "no UUID given")]) +def v0_compose_image(uuid): + """Return the output image for the build + + **/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. + """ + 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, api=0) + 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)
+ +
[docs]@v0_api.route("/compose/log", defaults={'uuid': ""}) +@v0_api.route("/compose/log/<uuid>") +@checkparams([("uuid","", "no UUID given")]) +def v0_compose_log_tail(uuid): + """Return the tail of the most currently relevant log + + **/api/v0/compose/log/<uuid>[?size=KiB]** + + Returns the end of either the anaconda log, the packaging log, or the + composer logs, depending on the progress of the compose. The size + parameter is optional and defaults to 1 MiB if it is not included. The + returned data is raw text from the end of the log file, starting on a + line boundary. + + 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) + """ + 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, api=0) + 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/f33-branch/_modules/pylorax/api/v1.html b/f33-branch/_modules/pylorax/api/v1.html new file mode 100644 index 00000000..87c82771 --- /dev/null +++ b/f33-branch/_modules/pylorax/api/v1.html @@ -0,0 +1,1243 @@ + + + + + + + + + + + pylorax.api.v1 — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.api.v1

+#
+# 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/>.
+#
+""" Setup v1 of the API server
+
+"""
+import logging
+log = logging.getLogger("lorax-composer")
+
+from flask import jsonify, request
+from flask import current_app as api
+
+from lifted.queue import get_upload, reset_upload, cancel_upload, delete_upload
+from lifted.providers import list_providers, resolve_provider, load_profiles, validate_settings, save_settings
+from lifted.providers import load_settings, delete_profile
+from pylorax.api.checkparams import checkparams
+from pylorax.api.compose import start_build
+from pylorax.api.errors import BAD_COMPOSE_TYPE, BUILD_FAILED, INVALID_CHARS, MISSING_POST, PROJECTS_ERROR
+from pylorax.api.errors import SYSTEM_SOURCE, UNKNOWN_BLUEPRINT, UNKNOWN_SOURCE, UNKNOWN_UUID, UPLOAD_ERROR
+from pylorax.api.errors import COMPOSE_ERROR
+from pylorax.api.flask_blueprint import BlueprintSkip
+from pylorax.api.queue import queue_status, build_status, uuid_status, uuid_schedule_upload, uuid_remove_upload
+from pylorax.api.queue import uuid_info
+from pylorax.api.projects import get_repo_sources, repo_to_source
+from pylorax.api.projects import new_repo_source
+from pylorax.api.regexes import VALID_API_STRING, VALID_BLUEPRINT_NAME
+import pylorax.api.toml as toml
+from pylorax.api.utils import blueprint_exists
+
+
+# Create the v1 routes Blueprint with skip_routes support
+v1_api = BlueprintSkip("v1_routes", __name__)
+
+
[docs]@v1_api.route("/projects/source/info", defaults={'source_ids': ""}) +@v1_api.route("/projects/source/info/<source_ids>") +@checkparams([("source_ids", "", "no source names given")]) +def v1_projects_source_info(source_ids): + """Return detailed info about the list of sources + + **/api/v1/projects/source/info/<source-ids>** + + Return information about the comma-separated list of source ids. 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" + ], + "id": "fedora", + "name": "Fedora $releasever - $basearch", + "proxy": "http://proxy.brianlane.com:8123", + "system": true, + "type": "yum-metalink", + "url": "https://mirrors.fedoraproject.org/metalink?repo=fedora-28&arch=x86_64" + } + } + } + + In v0 the ``name`` field was used for the id (a short name for the repo). In v1 ``name`` changed + to ``id`` and ``name`` is now used for the longer descriptive name of the repository. + """ + if VALID_API_STRING.match(source_ids) 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_ids == "*": + with api.config["DNFLOCK"].lock: + source_ids = ",".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_ids.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, api=1) + + 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)
+ +
[docs]@v1_api.route("/projects/source/new", methods=["POST"]) +def v1_projects_source_new(): + """Add a new package source. Or change an existing one + + **POST /api/v1/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:: + + { + "id": "custom-source-1", + "name": "Custom Package 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" + ] + } + + In v0 the ``name`` field was used for the id (a short name for the repo). In v1 ``name`` changed + to ``id`` and ``name`` is now used for the longer descriptive name of the repository. + """ + if request.headers['Content-Type'] == "text/x-toml": + source = toml.loads(request.data) + else: + source = request.get_json(cache=False) + + # Check for id in source, return error if not + if "id" not in source: + return jsonify(status=False, errors=[{"id": UNKNOWN_SOURCE, "msg": "'id' field is missing from API v1 request."}]), 400 + + system_sources = get_repo_sources("/etc/yum.repos.d/*.repo") + if source["id"] in system_sources: + return jsonify(status=False, errors=[{"id": SYSTEM_SOURCE, "msg": "%s is a system source, it cannot be changed." % source["id"]}]), 400 + + try: + # Remove it from the RepoDict (NOTE that this isn't explicitly supported by the DNF API) + with api.config["DNFLOCK"].lock: + repo_dir = api.config["COMPOSER_CFG"].get("composer", "repo_dir") + new_repo_source(api.config["DNFLOCK"].dbo, source["id"], source, repo_dir) + except Exception as e: + return jsonify(status=False, errors=[{"id": PROJECTS_ERROR, "msg": str(e)}]), 400 + + return jsonify(status=True)
+ +
[docs]@v1_api.route("/compose", methods=["POST"]) +def v1_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. + + **POST /api/v1/compose** + + Start a compose. The content type should be 'application/json' and the body of the POST + should look like this. The "upload" object is optional. + + The upload object can specify either a pre-existing profile to use (as returned by + `/uploads/providers`) or one-time use settings for the provider. + + Example with upload profile:: + + { + "blueprint_name": "http-server", + "compose_type": "tar", + "branch": "master", + "upload": { + "image_name": "My Image", + "provider": "azure", + "profile": "production-azure-settings" + } + } + + Example with upload settings:: + + { + "blueprint_name": "http-server", + "compose_type": "tar", + "branch": "master", + "upload": { + "image_name": "My Image", + "provider": "azure", + "settings": { + "resource_group": "SOMEBODY", + "storage_account_name": "ONCE", + "storage_container": "TOLD", + "location": "ME", + "subscription_id": "THE", + "client_id": "WORLD", + "secret": "IS", + "tenant": "GONNA" + } + } + } + + Pass it the name of the blueprint, the type of output (from + '/api/v1/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. + If an "upload" is given, it will schedule an upload to run when the build + finishes. + + Example response:: + + { + "build_id": "e6fa6db4-9c81-4b70-870f-a697ca405cdf", + "upload_id": "572eb0d0-5348-4600-9666-14526ba628bb", + "status": true + } + """ + # 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_BLUEPRINT_NAME.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 "upload" in compose: + try: + image_name = compose["upload"]["image_name"] + + if "profile" in compose["upload"]: + # Load a specific profile for this provider + profile = compose["upload"]["profile"] + provider_name = compose["upload"]["provider"] + settings = load_settings(api.config["COMPOSER_CFG"]["upload"], provider_name, profile) + else: + provider_name = compose["upload"]["provider"] + settings = compose["upload"]["settings"] + except KeyError as e: + errors.append({"id": UPLOAD_ERROR, "msg": f'Missing parameter {str(e)}!'}) + try: + provider = resolve_provider(api.config["COMPOSER_CFG"]["upload"], provider_name) + if "supported_types" in provider and compose_type not in provider["supported_types"]: + raise RuntimeError(f'Type "{compose_type}" is not supported by provider "{provider_name}"!') + validate_settings(api.config["COMPOSER_CFG"]["upload"], provider_name, settings, image_name) + except Exception as e: + errors.append({"id": UPLOAD_ERROR, "msg": str(e)}) + + 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 + + if "upload" in compose: + upload_id = uuid_schedule_upload( + api.config["COMPOSER_CFG"], + build_id, + provider_name, + image_name, + settings + ) + else: + upload_id = "" + + return jsonify(status=True, build_id=build_id, upload_id=upload_id)
+ +
[docs]@v1_api.route("/compose/queue") +def v1_compose_queue(): + """Return the status of the new and running queues + + **/api/v1/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", + "uploads": [ + { + "creation_time": 1568150660.524401, + "image_name": "glusterfs server", + "image_path": null, + "provider_name": "azure", + "settings": { + "client_id": "need", + "location": "need", + "resource_group": "group", + "secret": "need", + "storage_account_name": "need", + "storage_container": "need", + "subscription_id": "need", + "tenant": "need" + }, + "status": "WAITING", + "uuid": "21898dfd-9ac9-4e22-bb1d-7f12d0129e65" + } + ] + } + ] + } + """ + return jsonify(queue_status(api.config["COMPOSER_CFG"], api=1))
+ +
[docs]@v1_api.route("/compose/finished") +def v1_compose_finished(): + """Return the list of finished composes + + **/api/v1/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", + "uploads": [ + { + "creation_time": 1568150660.524401, + "image_name": "glusterfs server", + "image_path": "/var/lib/lorax/composer/results/e695affd-397f-4af9-9022-add2636e7459/disk.vhd", + "provider_name": "azure", + "settings": { + "client_id": "need", + "location": "need", + "resource_group": "group", + "secret": "need", + "storage_account_name": "need", + "storage_container": "need", + "subscription_id": "need", + "tenant": "need" + }, + "status": "WAITING", + "uuid": "21898dfd-9ac9-4e22-bb1d-7f12d0129e65" + } + ] + } + ] + } + """ + return jsonify(finished=build_status(api.config["COMPOSER_CFG"], "FINISHED", api=1))
+ +
[docs]@v1_api.route("/compose/failed") +def v1_compose_failed(): + """Return the list of failed composes + + **/api/v1/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", + "uploads": [ + { + "creation_time": 1568150660.524401, + "image_name": "http-server", + "image_path": null, + "provider_name": "azure", + "settings": { + "client_id": "need", + "location": "need", + "resource_group": "group", + "secret": "need", + "storage_account_name": "need", + "storage_container": "need", + "subscription_id": "need", + "tenant": "need" + }, + "status": "WAITING", + "uuid": "21898dfd-9ac9-4e22-bb1d-7f12d0129e65" + } + ] + } + ] + } + """ + return jsonify(failed=build_status(api.config["COMPOSER_CFG"], "FAILED", api=1))
+ +
[docs]@v1_api.route("/compose/status", defaults={'uuids': ""}) +@v1_api.route("/compose/status/<uuids>") +@checkparams([("uuids", "", "no UUIDs given")]) +def v1_compose_status(uuids): + """Return the status of the listed uuids + + **/api/v1/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", + "uploads": [ + { + "creation_time": 1568150660.524401, + "image_name": "glusterfs server", + "image_path": null, + "provider_name": "azure", + "settings": { + "client_id": "need", + "location": "need", + "resource_group": "group", + "secret": "need", + "storage_account_name": "need", + "storage_container": "need", + "subscription_id": "need", + "tenant": "need" + }, + "status": "WAITING", + "uuid": "21898dfd-9ac9-4e22-bb1d-7f12d0129e65" + } + ] + } + ] + } + """ + 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"], api=1) + queue_new = queue_status_dict["new"] + queue_running = queue_status_dict["run"] + candidates = queue_new + queue_running + build_status(api.config["COMPOSER_CFG"], api=1) + else: + candidates = [] + for uuid in [n.strip().lower() for n in uuids.split(",")]: + details = uuid_status(api.config["COMPOSER_CFG"], uuid, api=1) + 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)
+ +
[docs]@v1_api.route("/compose/info", defaults={'uuid': ""}) +@v1_api.route("/compose/info/<uuid>") +@checkparams([("uuid", "", "no UUID given")]) +def v1_compose_info(uuid): + """Return detailed info about a compose + + **/api/v1/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", + ... + }, + "uploads": [ + { + "creation_time": 1568150660.524401, + "image_name": "glusterfs server", + "image_path": "/var/lib/lorax/composer/results/c30b7d80-523b-4a23-ad52-61b799739ce8/disk.vhd", + "provider_name": "azure", + "settings": { + "client_id": "need", + "location": "need", + "resource_group": "group", + "secret": "need", + "storage_account_name": "need", + "storage_container": "need", + "subscription_id": "need", + "tenant": "need" + }, + "status": "FAILED", + "uuid": "21898dfd-9ac9-4e22-bb1d-7f12d0129e65" + } + ] + } + """ + 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, api=1) + 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)
+ +
[docs]@v1_api.route("/compose/uploads/schedule", defaults={'compose_uuid': ""}, methods=["POST"]) +@v1_api.route("/compose/uploads/schedule/<compose_uuid>", methods=["POST"]) +@checkparams([("compose_uuid", "", "no compose UUID given")]) +def v1_compose_uploads_schedule(compose_uuid): + """Schedule an upload of a compose to a given cloud provider + + **POST /api/v1/uploads/schedule/<compose_uuid>** + + The body can specify either a pre-existing profile to use (as returned by + `/uploads/providers`) or one-time use settings for the provider. + + Example with upload profile:: + + { + "image_name": "My Image", + "provider": "azure", + "profile": "production-azure-settings" + } + + Example with upload settings:: + + { + "image_name": "My Image", + "provider": "azure", + "settings": { + "resource_group": "SOMEBODY", + "storage_account_name": "ONCE", + "storage_container": "TOLD", + "location": "ME", + "subscription_id": "THE", + "client_id": "WORLD", + "secret": "IS", + "tenant": "GONNA" + } + } + + Example response:: + + { + "status": true, + "upload_id": "572eb0d0-5348-4600-9666-14526ba628bb" + } + """ + if VALID_API_STRING.match(compose_uuid) is None: + error = {"id": INVALID_CHARS, "msg": "Invalid characters in API path"} + return jsonify(status=False, errors=[error]), 400 + + parsed = request.get_json(cache=False) + if not parsed: + return jsonify(status=False, errors=[{"id": MISSING_POST, "msg": "Missing POST body"}]), 400 + + try: + image_name = parsed["image_name"] + provider_name = parsed["provider"] + if "profile" in parsed: + # Load a specific profile for this provider + profile = parsed["profile"] + settings = load_settings(api.config["COMPOSER_CFG"]["upload"], provider_name, profile) + else: + settings = parsed["settings"] + except KeyError as e: + error = {"id": UPLOAD_ERROR, "msg": f'Missing parameter {str(e)}!'} + return jsonify(status=False, errors=[error]), 400 + try: + compose_type = uuid_status(api.config["COMPOSER_CFG"], compose_uuid)["compose_type"] + provider = resolve_provider(api.config["COMPOSER_CFG"]["upload"], provider_name) + if "supported_types" in provider and compose_type not in provider["supported_types"]: + raise RuntimeError( + f'Type "{compose_type}" is not supported by provider "{provider_name}"!' + ) + except Exception as e: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(e)}]), 400 + + try: + upload_id = uuid_schedule_upload( + api.config["COMPOSER_CFG"], + compose_uuid, + provider_name, + image_name, + settings + ) + except RuntimeError as e: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(e)}]), 400 + return jsonify(status=True, upload_id=upload_id)
+ +
[docs]@v1_api.route("/upload/delete", defaults={"upload_uuid": ""}, methods=["DELETE"]) +@v1_api.route("/upload/delete/<upload_uuid>", methods=["DELETE"]) +@checkparams([("upload_uuid", "", "no upload UUID given")]) +def v1_compose_uploads_delete(upload_uuid): + """Delete an upload and disassociate it from its compose + + **DELETE /api/v1/upload/delete/<upload_uuid>** + + Example response:: + + { + "status": true, + "upload_id": "572eb0d0-5348-4600-9666-14526ba628bb" + } + """ + if VALID_API_STRING.match(upload_uuid) is None: + error = {"id": INVALID_CHARS, "msg": "Invalid characters in API path"} + return jsonify(status=False, errors=[error]), 400 + + try: + uuid_remove_upload(api.config["COMPOSER_CFG"], upload_uuid) + delete_upload(api.config["COMPOSER_CFG"]["upload"], upload_uuid) + except RuntimeError as error: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(error)}]) + return jsonify(status=True, upload_id=upload_uuid)
+ +
[docs]@v1_api.route("/upload/info", defaults={"upload_uuid": ""}) +@v1_api.route("/upload/info/<upload_uuid>") +@checkparams([("upload_uuid", "", "no UUID given")]) +def v1_upload_info(upload_uuid): + """Returns information about a given upload + + **GET /api/v1/upload/info/<upload_uuid>** + + Example response:: + + { + "status": true, + "upload": { + "creation_time": 1565620940.069004, + "image_name": "My Image", + "image_path": "/var/lib/lorax/composer/results/b6218e8f-0fa2-48ec-9394-f5c2918544c4/disk.vhd", + "provider_name": "azure", + "settings": { + "resource_group": "SOMEBODY", + "storage_account_name": "ONCE", + "storage_container": "TOLD", + "location": "ME", + "subscription_id": "THE", + "client_id": "WORLD", + "secret": "IS", + "tenant": "GONNA" + }, + "status": "FAILED", + "uuid": "b637c411-9d9d-4279-b067-6c8d38e3b211" + } + } + """ + if VALID_API_STRING.match(upload_uuid) is None: + return jsonify(status=False, errors=[{"id": INVALID_CHARS, "msg": "Invalid characters in API path"}]), 400 + + try: + upload = get_upload(api.config["COMPOSER_CFG"]["upload"], upload_uuid).summary() + except RuntimeError as error: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(error)}]) + return jsonify(status=True, upload=upload)
+ +
[docs]@v1_api.route("/upload/log", defaults={"upload_uuid": ""}) +@v1_api.route("/upload/log/<upload_uuid>") +@checkparams([("upload_uuid", "", "no UUID given")]) +def v1_upload_log(upload_uuid): + """Returns an upload's log + + **GET /api/v1/upload/log/<upload_uuid>** + + Example response:: + + { + "status": true, + "upload_id": "b637c411-9d9d-4279-b067-6c8d38e3b211", + "log": "< PLAY [localhost] >..." + } + """ + if VALID_API_STRING.match(upload_uuid) is None: + error = {"id": INVALID_CHARS, "msg": "Invalid characters in API path"} + return jsonify(status=False, errors=[error]), 400 + + try: + upload = get_upload(api.config["COMPOSER_CFG"]["upload"], upload_uuid) + except RuntimeError as error: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(error)}]) + return jsonify(status=True, upload_id=upload_uuid, log=upload.upload_log)
+ +
[docs]@v1_api.route("/upload/reset", defaults={"upload_uuid": ""}, methods=["POST"]) +@v1_api.route("/upload/reset/<upload_uuid>", methods=["POST"]) +@checkparams([("upload_uuid", "", "no UUID given")]) +def v1_upload_reset(upload_uuid): + """Reset an upload so it can be attempted again + + **POST /api/v1/upload/reset/<upload_uuid>** + + Optionally pass in a new image name and/or new settings. + + Example request:: + + { + "image_name": "My renamed image", + "settings": { + "resource_group": "ROLL", + "storage_account_name": "ME", + "storage_container": "I", + "location": "AIN'T", + "subscription_id": "THE", + "client_id": "SHARPEST", + "secret": "TOOL", + "tenant": "IN" + } + } + + Example response:: + + { + "status": true, + "upload_id": "c75d5d62-9d26-42fc-a8ef-18bb14679fc7" + } + """ + if VALID_API_STRING.match(upload_uuid) is None: + error = {"id": INVALID_CHARS, "msg": "Invalid characters in API path"} + return jsonify(status=False, errors=[error]), 400 + + parsed = request.get_json(cache=False) + image_name = parsed.get("image_name") if parsed else None + settings = parsed.get("settings") if parsed else None + + try: + reset_upload(api.config["COMPOSER_CFG"]["upload"], upload_uuid, image_name, settings) + except RuntimeError as error: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(error)}]) + return jsonify(status=True, upload_id=upload_uuid)
+ +
[docs]@v1_api.route("/upload/cancel", defaults={"upload_uuid": ""}, methods=["DELETE"]) +@v1_api.route("/upload/cancel/<upload_uuid>", methods=["DELETE"]) +@checkparams([("upload_uuid", "", "no UUID given")]) +def v1_upload_cancel(upload_uuid): + """Cancel an upload that is either queued or in progress + + **DELETE /api/v1/upload/cancel/<upload_uuid>** + + Example response:: + + { + "status": true, + "upload_id": "037a3d56-b421-43e9-9935-c98350c89996" + } + """ + if VALID_API_STRING.match(upload_uuid) is None: + error = {"id": INVALID_CHARS, "msg": "Invalid characters in API path"} + return jsonify(status=False, errors=[error]), 400 + + try: + cancel_upload(api.config["COMPOSER_CFG"]["upload"], upload_uuid) + except RuntimeError as error: + return jsonify(status=False, errors=[{"id": UPLOAD_ERROR, "msg": str(error)}]) + return jsonify(status=True, upload_id=upload_uuid)
+ +
[docs]@v1_api.route("/upload/providers") +def v1_upload_providers(): + """Return the information about all upload providers, including their + display names, expected settings, and saved profiles. Refer to the + `resolve_provider` function. + + **GET /api/v1/upload/providers** + + Example response:: + + { + "providers": { + "azure": { + "display": "Azure", + "profiles": { + "default": { + "client_id": "example", + ... + } + }, + "settings-info": { + "client_id": { + "display": "Client ID", + "placeholder": "", + "regex": "", + "type": "string" + }, + ... + }, + "supported_types": ["vhd"] + }, + ... + } + } + """ + + ucfg = api.config["COMPOSER_CFG"]["upload"] + + provider_names = list_providers(ucfg) + + def get_provider_info(provider_name): + provider = resolve_provider(ucfg, provider_name) + provider["profiles"] = load_profiles(ucfg, provider_name) + return provider + + providers = {provider_name: get_provider_info(provider_name) + for provider_name in provider_names} + return jsonify(status=True, providers=providers)
+ +
[docs]@v1_api.route("/upload/providers/save", methods=["POST"]) +def v1_providers_save(): + """Save provider settings as a profile for later use + + **POST /api/v1/upload/providers/save** + + Example request:: + + { + "provider": "azure", + "profile": "my-profile", + "settings": { + "resource_group": "SOMEBODY", + "storage_account_name": "ONCE", + "storage_container": "TOLD", + "location": "ME", + "subscription_id": "THE", + "client_id": "WORLD", + "secret": "IS", + "tenant": "GONNA" + } + } + + Saving to an existing profile will overwrite it. + + Example response:: + + { + "status": true + } + """ + parsed = request.get_json(cache=False) + + if parsed is None: + return jsonify(status=False, errors=[{"id": MISSING_POST, "msg": "Missing POST body"}]), 400 + + try: + provider_name = parsed["provider"] + profile = parsed["profile"] + settings = parsed["settings"] + except KeyError as e: + error = {"id": UPLOAD_ERROR, "msg": f'Missing parameter {str(e)}!'} + return jsonify(status=False, errors=[error]), 400 + try: + save_settings(api.config["COMPOSER_CFG"]["upload"], provider_name, profile, settings) + except Exception as e: + error = {"id": UPLOAD_ERROR, "msg": str(e)} + return jsonify(status=False, errors=[error]) + return jsonify(status=True)
+ +
[docs]@v1_api.route("/upload/providers/delete", defaults={"provider_name": "", "profile": ""}, methods=["DELETE"]) +@v1_api.route("/upload/providers/delete/<provider_name>/<profile>", methods=["DELETE"]) +@checkparams([("provider_name", "", "no provider name given"), ("profile", "", "no profile given")]) +def v1_providers_delete(provider_name, profile): + """Delete a provider's profile settings + + **DELETE /api/v1/upload/providers/delete/<provider_name>/<profile>** + + Example response:: + + { + "status": true + } + """ + if None in (VALID_API_STRING.match(provider_name), VALID_API_STRING.match(profile)): + error = {"id": INVALID_CHARS, "msg": "Invalid characters in API path"} + return jsonify(status=False, errors=[error]), 400 + + try: + delete_profile(api.config["COMPOSER_CFG"]["upload"], provider_name, profile) + except Exception as e: + error = {"id": UPLOAD_ERROR, "msg": str(e)} + return jsonify(status=False, errors=[error]) + return jsonify(status=True)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/api/workspace.html b/f33-branch/_modules/pylorax/api/workspace.html new file mode 100644 index 00000000..366be10c --- /dev/null +++ b/f33-branch/_modules/pylorax/api/workspace.html @@ -0,0 +1,330 @@ + + + + + + + + + + + pylorax.api.workspace — Lorax 33.10 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_filename(repo, branch, recipe_name): + """Return the path and filename of the workspace recipe + + :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: workspace recipe path and filename + :rtype: str + """ + ws_dir = workspace_dir(repo, branch) + return joinpaths(ws_dir, recipe_filename(recipe_name))
+ + +
[docs]def workspace_exists(repo, branch, recipe_name): + """Return true of the workspace recipe exists + + :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: True if the file exists + :rtype: bool + """ + return os.path.exists(workspace_filename(repo, branch, recipe_name))
+ + +
[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 + """ + filename = workspace_filename(repo, branch, recipe_name) + if os.path.exists(filename): + os.unlink(filename)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/base.html b/f33-branch/_modules/pylorax/base.html new file mode 100644 index 00000000..dd6f36b9 --- /dev/null +++ b/f33-branch/_modules/pylorax/base.html @@ -0,0 +1,268 @@ + + + + + + + + + + + pylorax.base — Lorax 33.10 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/f33-branch/_modules/pylorax/buildstamp.html b/f33-branch/_modules/pylorax/buildstamp.html new file mode 100644 index 00000000..e9dfc42e --- /dev/null +++ b/f33-branch/_modules/pylorax/buildstamp.html @@ -0,0 +1,267 @@ + + + + + + + + + + + pylorax.buildstamp — Lorax 33.10 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/f33-branch/_modules/pylorax/cmdline.html b/f33-branch/_modules/pylorax/cmdline.html new file mode 100644 index 00000000..6e52388d --- /dev/null +++ b/f33-branch/_modules/pylorax/cmdline.html @@ -0,0 +1,522 @@ + + + + + + + + + + + pylorax.cmdline — Lorax 33.10 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.") + optional.add_argument("--skip-branding", action="store_true", default=False, + help="Disable automatic branding package selection. Use --installpkgs to add custom branding.") + + # dracut arguments + dracut_group = parser.add_argument_group("dracut arguments: (default: %s)" % dracut_default) + dracut_group.add_argument("--dracut-conf", + help="Path to a dracut.conf file to use instead of the " + "default arguments. See the dracut.conf(5) manpage.") + 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 defaults.") + + # 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: (default: %s)" % dracut_default) + dracut_group.add_argument("--dracut-conf", + help="Path to a dracut.conf file to use instead of the " + "default arguments. See the dracut.conf(5) manpage.") + 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 defaults.") + + # 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("--project", default="Linux", + help="substituted for @PROJECT@ in bootloader config files") + parser.add_argument("--releasever", default="32", + help="substituted for @VERSION@ in bootloader config files") + parser.add_argument("--volid", default=None, help="volume id") + parser.add_argument("--squashfs-only", action="store_true", default=False, + help="Use a plain squashfs filesystem for the runtime.") + 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/f33-branch/_modules/pylorax/creator.html b/f33-branch/_modules/pylorax/creator.html new file mode 100644 index 00000000..bc25fdde --- /dev/null +++ b/f33-branch/_modules/pylorax/creator.html @@ -0,0 +1,957 @@ + + + + + + + + + + + pylorax.creator — Lorax 33.10 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-arg or --dracut-conf
+DRACUT_DEFAULT = ["--xz", "--add", "livenet dmsquash-live dmsquash-live-ntfs 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 and not opts.compress_args: + # default to bcj when using xz + compressargs = ["-Xbcj", arch.bcj] + elif opts.compress_args: + compressargs = [] + for arg in opts.compress_args: + compressargs += arg.split(" ", 1) + else: + compressargs = [] + return (compression, compressargs)
+ +
[docs]def dracut_args(opts): + """Return a list of the args to pass to dracut + + Return the default argument list unless one of the dracut cmdline arguments + has been used. + """ + if opts.dracut_conf: + return ["--conf", opts.dracut_conf] + elif opts.dracut_args: + args = [] + for arg in opts.dracut_args: + args += arg.split(" ", 1) + return args + else: + return DRACUT_DEFAULT
+ +
[docs]def make_appliance(disk_img, name, template, outfile, networks=None, ram=1024, + vcpus=1, arch=None, title="Linux", project="Linux", + releasever="32"): + """ + 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 32 + """ + 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 + :returns: rc of squashfs creation + :rtype: int + """ + 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) + + rb = RuntimeBuilder(product, arch, fake_dbo) + compression, compressargs = squashfs_args(opts) + + if opts.squashfs_only: + log.info("Creating a squashfs only runtime") + return rb.create_squashfs_runtime(joinpaths(work_dir, RUNTIME), size=size, + compression=compression, compressargs=compressargs) + else: + log.info("Creating a squashfs+ext4 runtime") + return 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 + """ + # cmdline dracut args override the defaults, but need to be parsed + log.info("dracut args = %s", dracut_args(opts)) + + dracut = ["dracut", "--nomdadmconf", "--nolvmconf"] + dracut_args(opts) + + 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") + + 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) + log.info("dracut warnings about /proc are safe to ignore") + + 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)
+ +
[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")) + rc = execWithRedirect("/bin/ln", ["-s", joinpaths(work_dir, "images"), + joinpaths(mount_dir, "images")]) + if rc: + raise RuntimeError("Failed to symlink images from mount_dir to work_dir") + + # 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") + log.info("dracut args = %s", dracut_args(opts)) + tb.rebuild_initrds(add_args=dracut_args(opts)) + 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 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) + rc = mksquashfs(squashfs_root_dir, joinpaths(work_dir, live_image_name), compression, compressargs) + if rc != 0: + log.error("mksquashfs failed to create %s", live_image_name) + return None + + 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 + with Mount(disk_img, opts="loop") as mount_dir: + rc = make_runtime(opts, mount_dir, work_dir, calculate_disk_size(opts, ks)/1024.0) + if rc != 0: + log.error("make_runtime failed with rc = %d. See program.log", rc) + raise RuntimeError("make_runtime failed with rc = %d" % rc) + if cancel_func and cancel_func(): + raise RuntimeError("ISO creation canceled") + + 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: + rc = make_runtime(opts, img_mount.mount_dir, work_dir, calculate_disk_size(opts, ks)/1024.0) + if rc != 0: + log.error("make_runtime failed with rc = %d. See program.log", rc) + raise RuntimeError("make_runtime failed with rc = %d" % rc) + 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/f33-branch/_modules/pylorax/decorators.html b/f33-branch/_modules/pylorax/decorators.html new file mode 100644 index 00000000..062c3392 --- /dev/null +++ b/f33-branch/_modules/pylorax/decorators.html @@ -0,0 +1,231 @@ + + + + + + + + + + + pylorax.decorators — Lorax 33.10 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/f33-branch/_modules/pylorax/discinfo.html b/f33-branch/_modules/pylorax/discinfo.html new file mode 100644 index 00000000..c006b79e --- /dev/null +++ b/f33-branch/_modules/pylorax/discinfo.html @@ -0,0 +1,246 @@ + + + + + + + + + + + pylorax.discinfo — Lorax 33.10 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/f33-branch/_modules/pylorax/dnfbase.html b/f33-branch/_modules/pylorax/dnfbase.html new file mode 100644 index 00000000..23c76d66 --- /dev/null +++ b/f33-branch/_modules/pylorax/dnfbase.html @@ -0,0 +1,388 @@ + + + + + + + + + + + pylorax.dnfbase — Lorax 33.10 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="32", + 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'] + # Log details about the solver + conf.debug_solver = True + + 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/f33-branch/_modules/pylorax/dnfhelper.html b/f33-branch/_modules/pylorax/dnfhelper.html new file mode 100644 index 00000000..8e1b8917 --- /dev/null +++ b/f33-branch/_modules/pylorax/dnfhelper.html @@ -0,0 +1,311 @@ + + + + + + + + + + + pylorax.dnfhelper — Lorax 33.10 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/f33-branch/_modules/pylorax/executils.html b/f33-branch/_modules/pylorax/executils.html new file mode 100644 index 00000000..5e9ce93a --- /dev/null +++ b/f33-branch/_modules/pylorax/executils.html @@ -0,0 +1,550 @@ + + + + + + + + + + + pylorax.executils — Lorax 33.10 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, + 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/f33-branch/_modules/pylorax/imgutils.html b/f33-branch/_modules/pylorax/imgutils.html new file mode 100644 index 00000000..02742d08 --- /dev/null +++ b/f33-branch/_modules/pylorax/imgutils.html @@ -0,0 +1,755 @@ + + + + + + + + + + + pylorax.imgutils — Lorax 33.10 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/f33-branch/_modules/pylorax/installer.html b/f33-branch/_modules/pylorax/installer.html new file mode 100644 index 00000000..6fb2c1d4 --- /dev/null +++ b/f33-branch/_modules/pylorax/installer.html @@ -0,0 +1,879 @@ + + + + + + + + + + + pylorax.installer — Lorax 33.10 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", + "ppc64le": "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. + + Anaconda may also leave /run/anaconda.pid behind, clean that up as well. + """ + # Anaconda may not clean up its /var/run/anaconda.pid file + # Make sure the process is really finished (it should be, since it was started from a subprocess call) + # and then remove the pid file. + if os.path.exists("/var/run/anaconda.pid"): + # lorax-composer runs anaconda using unshare so the pid is always 1 + if open("/var/run/anaconda.pid").read().strip() == "1": + os.unlink("/var/run/anaconda.pid") + + 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 + # Preload libgomp.so.1 to workaround rhbz#1722181 + log.info("Running anaconda.") + try: + unshare_args = [ "--pid", "--kill-child", "--mount", "--propagation", "unchanged", "anaconda" ] + args + for line in execReadlines("unshare", unshare_args, reset_lang=False, + env_add={"ANACONDA_PRODUCTNAME": opts.project, + "ANACONDA_PRODUCTVERSION": opts.releasever, + "LD_PRELOAD": "libgomp.so.1"}, + 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/f33-branch/_modules/pylorax/ltmpl.html b/f33-branch/_modules/pylorax/ltmpl.html new file mode 100644 index 00000000..afb74433 --- /dev/null +++ b/f33-branch/_modules/pylorax/ltmpl.html @@ -0,0 +1,1085 @@ + + + + + + + + + + + pylorax.ltmpl — Lorax 33.10 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.abc
+
+
[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.abc.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_package_log(self): + """ + Write the list of installed packages to /root/ on the boot.iso + + 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 + The non-debuginfo packages are written to /root/lorax-packages.log + """ + os.makedirs(self._out("root/"), exist_ok=True) + available = self.dbo.sack.query().available() + pkgs = [] + debug_pkgs = [] + for p in list(self.dbo.transaction.install_set): + pkgs.append(f"{p.name}-{p.version}-{p.release}.{p.arch}") + if available.filter(name=p.name+"-debuginfo"): + debug_pkgs.append(f"{p.name}-debuginfo-{p.epoch}:{p.version}-{p.release}") + + with open(self._out("root/lorax-packages.log"), "w") as f: + f.write("\n".join(sorted(pkgs))) + f.write("\n") + + if debug_pkgs: + with open(self._out("root/debug-pkgs.log"), "w") as f: + f.write("\n".join(sorted(debug_pkgs))) + f.write("\n") + +
[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") + + # Write out the packages installed, including debuginfo packages + self._write_package_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/f33-branch/_modules/pylorax/monitor.html b/f33-branch/_modules/pylorax/monitor.html new file mode 100644 index 00000000..30e40b86 --- /dev/null +++ b/f33-branch/_modules/pylorax/monitor.html @@ -0,0 +1,404 @@ + + + + + + + + + + + pylorax.monitor — Lorax 33.10 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/f33-branch/_modules/pylorax/mount.html b/f33-branch/_modules/pylorax/mount.html new file mode 100644 index 00000000..c861493b --- /dev/null +++ b/f33-branch/_modules/pylorax/mount.html @@ -0,0 +1,305 @@ + + + + + + + + + + + pylorax.mount — Lorax 33.10 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
+import pycdlib
+from pycdlib.pycdlibexception import PyCdlibException
+
+from pylorax.imgutils import mount, umount
+
+
[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"), + ("/images/pxeboot/vmlinuz", "/images/pxeboot/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 + """ + try: + iso = pycdlib.PyCdlib() + iso.open(self.iso_path) + self.label = iso.pvd.volume_identifier.decode("UTF-8").strip() + except PyCdlibException as e: + log.error("Problem reading label from %s: %s", self.iso_path, e)
+
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/sysutils.html b/f33-branch/_modules/pylorax/sysutils.html new file mode 100644 index 00000000..db76cd9a --- /dev/null +++ b/f33-branch/_modules/pylorax/sysutils.html @@ -0,0 +1,361 @@ + + + + + + + + + + + pylorax.sysutils — Lorax 33.10 documentation + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

Source code for pylorax.sysutils

+#
+# sysutils.py
+#
+# Copyright (C) 2009-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/>.
+#
+# 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'] + +def read_tail(path, size): + """Read up to `size` kibibytes from the end of a file""" + + # NOTE: In py3 text files are unicode, not bytes so we have to open it as bytes + with open(path, "rb") as f: + return _read_file_end(f, size) + +def _read_file_end(f, size): + """Read the end of a file + + This skips to the next line to avoid starting in the middle of a unicode character. + And returns "" in the case of a UnicodeDecodeError + """ + f.seek(0, 2) + end = f.tell() + if end < 1024 * size: + f.seek(0, 0) + else: + f.seek(end - (1024 * size)) + data = f.read() + try: + # Find the first newline in the block + newline = min(1+data.find(b'\n'), len(data)) + text = data[newline:].decode("UTF-8") + except UnicodeDecodeError: + return "" + return text +
+ +
+ +
+ + +
+
+ +
+ +
+ + + + + + + + + + + + \ No newline at end of file diff --git a/f33-branch/_modules/pylorax/treebuilder.html b/f33-branch/_modules/pylorax/treebuilder.html new file mode 100644 index 00000000..ae2615f2 --- /dev/null +++ b/f33-branch/_modules/pylorax/treebuilder.html @@ -0,0 +1,624 @@ + + + + + + + + + + + pylorax.treebuilder — Lorax 33.10 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 subprocess import CalledProcessError
+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',
+    '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, + skip_branding=False): + 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() + self._skip_branding = skip_branding + + def _install_branding(self): + """Select the branding from the available 'system-release' packages + The *best* way to control this is to have a single package in the repo provide 'system-release' + When there are more than 1 package it will: + - Make a list of the available packages + - If variant is set look for a package ending with lower(variant) and use that + - If there are one or more non-generic packages, use the first one after sorting + """ + if self._skip_branding: + return + + release = None + q = self.dbo.sack.query() + a = q.available() + pkgs = sorted([p.name for p in a.filter(provides='system-release') + if not p.name.startswith("generic")]) + if not pkgs: + logger.error("No system-release packages found, could not get the release") + return + + logger.debug("system-release packages: %s", pkgs) + if self.vars.product.variant: + variant = [p for p in pkgs if p.endswith("-"+self.vars.product.variant.lower())] + if variant: + release = variant[0] + if not release: + release = pkgs[0] + + # 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 + return 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")) + + # Catch problems with the rootfs being too small and clearly log them + try: + imgutils.mkrootfsimg(self.vars.root, joinpaths(workdir, "LiveOS/rootfs.img"), + "Anaconda", size=size) + except CalledProcessError as e: + if e.stdout and "No space left on device" in e.stdout: + logger.error("The rootfs ran out of space with size=%d", size) + raise + + # squash the live rootfs and clean up workdir + rc = imgutils.mksquashfs(workdir, outfile, compression, compressargs) + remove(workdir) + return rc
+ +
[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") + + 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) + logger.info("dracut warnings about /proc are safe to ignore") + + 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)
+ +
[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/f33-branch/_modules/pylorax/treeinfo.html b/f33-branch/_modules/pylorax/treeinfo.html new file mode 100644 index 00000000..0fb559b7 --- /dev/null +++ b/f33-branch/_modules/pylorax/treeinfo.html @@ -0,0 +1,264 @@ + + + + + + + + + + + pylorax.treeinfo — Lorax 33.10 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/f33-branch/_sources/composer-cli.rst.txt b/f33-branch/_sources/composer-cli.rst.txt new file mode 100644 index 00000000..83612e1d --- /dev/null +++ b/f33-branch/_sources/composer-cli.rst.txt @@ -0,0 +1,203 @@ +composer-cli +============ + +:Authors: + Brian C. Lane + +``composer-cli`` is an interactive tool for use with a WELDR API server, +managing blueprints, exploring available packages, and building new images. +`lorax-composer ` and `osbuild-composer +` both implement compatible servers. + +It requires the server 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. + +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 + +You can optionally start an upload of the finished image, see `Image Uploads`_ for +more information. + + +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 + + +Image Uploads +------------- + +``composer-cli`` can upload the images to a number of services, including AWS, +OpenStack, and vSphere. The upload can be started when the build is finished, +by using ``composer-cli compose start ...`` or an existing image can be uploaded +with ``composer-cli upload start ...``. In order to access the service you need +to pass authentication details to composer-cli using a TOML file, or reference +a previously saved profile. + +``lorax-composer`` and ``osbuild-composer`` handle this differently, with +``osbuild-composer`` you can currently only specify upload targets during the +compose process. + + +Providers +--------- + +Providers are the services providers with Ansible playbook support under +``/usr/share/lorax/lifted/providers/``, you will need to gather some provider +specific information in order to authenticate with it. You can view the +required fields using ``composer-cli providers template ``, eg. for AWS +you would run:: + + composer-cli upload template aws + +The output looks like this:: + + provider = "aws" + + [settings] + aws_access_key = "AWS Access Key" + aws_bucket = "AWS Bucket" + aws_region = "AWS Region" + aws_secret_key = "AWS Secret Key" + +Save this into an ``aws-credentials.toml`` file and use it when running ``start``. + +AWS +^^^ + +The access key and secret key can be created by going to the +``IAM->Users->Security Credentials`` section and creating a new access key. The +secret key will only be shown when it is first created so make sure to record +it in a secure place. The region should be the region that you want to use the +AMI in, and the bucket can be an existing bucket, or a new one, following the +normal AWS bucket naming rules. It will be created if it doesn't already exist. + +When uploading the image it is first uploaded to the s3 bucket, and then +converted to an AMI. If the conversion is successful the s3 object will be +deleted. If it fails, re-trying after correcting the problem will re-use the +object if you have not deleted it in the meantime, speeding up the process. + + +Profiles +-------- + +Profiles store the authentication settings associated with a specific provider. +Providers can have multiple profiles, as long as their names are unique. For +example, you may have one profile for testing and another for production +uploads. + +Profiles are created by pushing the provider settings template to the server using +``composer-cli providers push `` where ``PROFILE.TOML`` is the same as the +provider template, but with the addition of a ``profile`` field. For example, an AWS +profile named ``test-uploads`` would look like this:: + + provider = "aws" + profile = "test-uploads" + + [settings] + aws_access_key = "AWS Access Key" + aws_bucket = "AWS Bucket" + aws_region = "AWS Region" + aws_secret_key = "AWS Secret Key" + +You can view the profile by using ``composer-cli providers aws test-uploads``. + + +Build an image and upload results +--------------------------------- + +If you have a profile named ``test-uploads``:: + + composer-cli compose start example-http-server ami "http image" aws test-uploads + +Or if you have the settings stored in a TOML file:: + + composer-cli compose start example-http-server ami "http image" aws-settings.toml + +It will return the UUID of the image build, and the UUID of the upload. Once +the build has finished successfully it will start the upload process, which you +can monitor with ``composer-cli upload info `` + +You can also view the upload logs from the Ansible playbook with:: + + ``composer-cli upload log `` + +The type of the image must match the type supported by the provider. + + +Upload an existing image +------------------------ + +You can upload previously built images, as long as they are in the ``FINISHED`` state, using ``composer-cli upload start ...```. If you have a profile named ``test-uploads``:: + + composer-cli upload start "http-image" aws test-uploads + +Or if you have the settings stored in a TOML file:: + + composer-cli upload start "http-image" aws-settings.toml + +This will output the UUID of the upload, which can then be used to monitor the status in the same way +described above. + + +Debugging +--------- + +There are a couple of arguments that can be helpful when debugging problems. +These are only meant for debugging and should not be used to script access to +the API. If you need to do that you can communicate with it directly in the +language of your choice. + +``--json`` will return the server's response as a nicely formatted json output +instead of printing what the command would usually print. + +``--test=1`` will cause a compose start to start creating an image, and then +end with a failed state. + +``--test=2`` will cause a compose to start and then end with a finished state, +without actually composing anything. diff --git a/f33-branch/_sources/composer.cli.rst.txt b/f33-branch/_sources/composer.cli.rst.txt new file mode 100644 index 00000000..4dd2e240 --- /dev/null +++ b/f33-branch/_sources/composer.cli.rst.txt @@ -0,0 +1,101 @@ +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.providers module +----------------------------- + +.. automodule:: composer.cli.providers + :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.upload module +-------------------------- + +.. automodule:: composer.cli.upload + :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/f33-branch/_sources/composer.rst.txt b/f33-branch/_sources/composer.rst.txt new file mode 100644 index 00000000..1ff06326 --- /dev/null +++ b/f33-branch/_sources/composer.rst.txt @@ -0,0 +1,37 @@ +composer package +================ + +Subpackages +----------- + +.. toctree:: + :maxdepth: 4 + + 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/f33-branch/_sources/index.rst.txt b/f33-branch/_sources/index.rst.txt new file mode 100644 index 00000000..40a46d5e --- /dev/null +++ b/f33-branch/_sources/index.rst.txt @@ -0,0 +1,40 @@ +.. 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 + mkksiso + product-images + modules + +Documentation for other Lorax Branches +====================================== + +* `Fedora 32 `_ +* `Fedora 31 `_ +* `Fedora 30 `_ +* `Fedora 29 `_ +* `Fedora 28 `_ +* `RHEL8 lorax-composer `_ +* `RHEL7 lorax-composer `_ + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/f33-branch/_sources/intro.rst.txt b/f33-branch/_sources/intro.rst.txt new file mode 100644 index 00000000..01857ee9 --- /dev/null +++ b/f33-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/f33-branch/_sources/lifted.rst.txt b/f33-branch/_sources/lifted.rst.txt new file mode 100644 index 00000000..a9c4b004 --- /dev/null +++ b/f33-branch/_sources/lifted.rst.txt @@ -0,0 +1,46 @@ +lifted package +============== + +Submodules +---------- + +lifted.config module +-------------------- + +.. automodule:: lifted.config + :members: + :undoc-members: + :show-inheritance: + +lifted.providers module +----------------------- + +.. automodule:: lifted.providers + :members: + :undoc-members: + :show-inheritance: + +lifted.queue module +------------------- + +.. automodule:: lifted.queue + :members: + :undoc-members: + :show-inheritance: + +lifted.upload module +-------------------- + +.. automodule:: lifted.upload + :members: + :undoc-members: + :show-inheritance: + + +Module contents +--------------- + +.. automodule:: lifted + :members: + :undoc-members: + :show-inheritance: diff --git a/f33-branch/_sources/livemedia-creator.rst.txt b/f33-branch/_sources/livemedia-creator.rst.txt new file mode 100644 index 00000000..962be311 --- /dev/null +++ b/f33-branch/_sources/livemedia-creator.rst.txt @@ -0,0 +1,670 @@ +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 + + --macboot : @replace + Make the iso bootable on UEFI based Mac systems + + Default: True + + --nomacboot : @replace + Do not create a Mac bootable iso + + Default: False + + +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
+ + + +
+ + + + + +
+ +
+ + + + + + + + + + + + + + + + + +
+ + + + +
+
+
+
+ +

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
+from composer.cli.upload import upload_cmd
+from composer.cli.providers import providers_cmd
+
+command_map = {
+    "blueprints": blueprints_cmd,
+    "modules":    modules_cmd,
+    "projects":   projects_cmd,
+    "compose":    compose_cmd,
+    "sources":    sources_cmd,
+    "status":     status_cmd,
+    "upload":     upload_cmd,
+    "providers":  providers_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
+
+ +
+ +
+ + +
+
+ +
+ +