././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2488828 murano-agent-9.0.0/0000775000175000017500000000000000000000000014140 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/.stestr.conf0000664000175000017500000000007100000000000016407 0ustar00zuulzuul00000000000000[DEFAULT] test_path=./muranoagent/tests/unit top_dir=./ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/.zuul.yaml0000664000175000017500000000024500000000000016102 0ustar00zuulzuul00000000000000- project: templates: - check-requirements - openstack-lower-constraints-jobs - openstack-python3-yoga-jobs - release-notes-jobs-python3 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/AUTHORS0000664000175000017500000000634700000000000015222 0ustar00zuulzuul0000000000000098k <18552437190@163.com> Alexander Shlykov Alexey Deryugin Andreas Jaeger Andy Botting Angus Salkeld Ankur Rishi Artem Tiumentcev AvnishPal Cao Xuan Hoang Chuck Short Corey Bryant Dmitrii Dovbii Dmitry Teselkin Dmytro Dovbii Doug Hellmann Ekaterina Chernova Ekaterina Fedorova Felipe Monteiro Flavio Percoco Georgiy Okrokvertskhov Georgy Okrokvertskhov Gerry Buteau Ghanshyam Mann Hangdong Zhang Henar Muñoz Frutos Hervé Beraud Hidekazu Nakamura Ian Wienand Jeremy Stanley Jose Phillips Kirill Zaitsev Lin Yang LiuNanke Longgeek Lucky samadhiya M V P Nitesh MStolyarenko Ngo Quoc Cuong Nikolay Starodubtsev Olivier Lemasle OpenStack Release Bot Ravi Shekhar Jethani Renat Akhmerov Robert Collins Ruslan Kamaldinov Sean McGinnis Serg Melikyan Serg Melikyan Sergey Lukjanov Sergey Melikyan Sergey Murashov Sergey Vilgelm Stan Lagun Stan Lagun Stanislav Lagun Swapnil Kulkarni (coolsvap) THOMAS J. COCOZZELLO Tetiana Lashchova Thierry Carrez Timur Nurlygayanov Timur Sufiev Victor Ryzhenkin Victor Stinner Vu Cong Tuan Yushiro FURUKAWA binean deepakmourya ghanshyam hparekh huang.zhiping huangtianhua janonymous jeremy.zhang melissaml rajat29 ricolin ting.wang wanghui yatin zhu.rong zhulingjie zhurong ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/CONTRIBUTING.rst0000664000175000017500000000114300000000000016600 0ustar00zuulzuul00000000000000The source repository for this project can be found at: https://opendev.org/openstack/murano-agent Pull requests submitted through GitHub are not monitored. To start contributing to OpenStack, follow the steps in the contribution guide to set up and use Gerrit: https://docs.openstack.org/contributors/code-and-documentation/quick-start.html Bugs should be filed on Launchpad: https://bugs.launchpad.net/murano For more specific information about contributing to this repository, see the murano-agent contributor guide: https://docs.openstack.org/murano/latest/contributor/contributing.html ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/ChangeLog0000664000175000017500000005744600000000000015732 0ustar00zuulzuul00000000000000CHANGES ======= 9.0.0 ----- * Fix murano-agent DIB * Add Python3 yoga unit tests * Update master for stable/xena 8.0.0 ----- * [community goal] Update contributor documentation * Fix lower-constraints job * Add Python3 xena unit tests * Update master for stable/wallaby 7.0.0 ----- * Fix another base64 python3 issue * Fix base64 usage for Python 3 * Add Python3 wallaby unit tests * Update master for stable/victoria 6.0.0 ----- * [goal] Migrate testing to ubuntu focal * Use unittest.mock instead of mock * Switch to newer openstackdocstheme and reno versions * Fix hacking min version to 3.0.1 * Monkey patch original current\_thread \_active * Bump default tox env from py37 to py38 * Add py38 package metadata * Add Python3 victoria unit tests * Update master for stable/ussuri 5.0.0.0rc1 ---------- * Use unittest.mock instead of third party mock * Remove six usage * Cleanup py27 support * Update to hacking 3.0 * Update hacking for Python3 * [ussuri][goal] Drop python 2.7 support and testing * Update master for stable/train 4.0.0 ----- * Add Python 3 Train unit tests * Update contraints url * Fix sphinx requirements * Replace git.openstack.org URLs with opendev.org URLs * OpenDev Migration Patch * Dropping the py35 testing * Update master for stable/stein * Replace openstack.org git:// URLs with https:// 3.6.0 ----- * add python 3.7 unit test job * Add py36 to classifier and update tox version * Use template for lower-constraints * Change openstack-dev to openstack-discuss * Fix unit tests for python3.6 * add python 3.6 unit test job * switch documentation job to new PTI * import zuul job settings from project-config * Remove the unused tools scripts * murano-aget PTI docs build * Fix murano agent docs generate error * Update reno for stable/rocky 3.5.1 ----- * Switch to stestr 3.5.0 ----- * fix tox python3 overrides * uncap eventlet * Update links in README * add lower-constraints job * Updated from global requirements * Updated from global requirements * Updated from global requirements * Update reno for stable/queens 3.4.0 ----- * Updated from global requirements * Fix: config generation * Updated from global requirements * Updated from global requirements * Message signing implementation for legacy Windows agent * Murano-agent side implementation of message signing * Updated from global requirements * Updated from global requirements * Updated from global requirements * Tighten access to runtime agent folders * Remove setting of version/release from releasenotes * Updated from global requirements * Updated from global requirements * Updated from global requirements * Fix to use . to source script files * Updated from global requirements * Updated from global requirements * Updated from global requirements * Update reno for stable/pike 3.3.0 ----- * Updated from global requirements * Mask sensitive information before logging execution plan * Update the documentation link for doc migration * switch to openstackdocstheme * Remove usage of parameter enforce\_type * Updated from global requirements * Updated from global requirements * Change author in setup.cfg * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Fix doc generation for Python3 * Updated from global requirements * Optimize the link address * Updated from global requirements * Replace uuid.uuid4() with uuidutils.generate\_uuid() * Use HostAddressOpt for opts that accept IP and hostnames * Adds TLS/SSL Version Support to Murano Agent * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Update test requirement * Use openstack cmd instead in readme.rst * Remove support for py34 * Update reno for stable/ocata 3.2.0 ----- * Updated from global requirements 3.1.0 ----- * Marking rabbitmq password config property as secret * Add debug to tox enviroment * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Show team and repo badges on README * Fixed issues on Python 3 * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Enable release notes translation * Updated from global requirements * Fix coverage option and execution * Updated from global requirements * Updated from global requirements * Fix Null Reference exception in Windows agent PS scripts * Fix LOG.warn to LOG.warning * update homepage with developer documentation page * Updated from global requirements * fix the home-page URL to be valid * Update reno for stable/newton 3.0.0.0rc1 ---------- * Mention DIB\_CLOUD\_INIT\_DATASOURCES in README * TrivialFix: Remove cfg import unused * TrivialFix: Remove logging import unused 3.0.0.0b3 --------- * [docs] Update Readme with correct Doc URL * Update tox.ini for upper constraints * Trivial: Add python identifiers in setup.cfg * Chef executor unit tests now compare dicts instead of strings * Add Python 3.5 classifier and venv * Updated from global requirements * Drop \*openstack/common\* in flake8 exclude list * Remove discover from test-requirements 3.0.0.0b2 --------- * Updated from global requirements * Use upper-constraints in tox test environments * Updated from global requirements * Updated from global requirements * Updated from global requirements * Python 3: add py34 test environment to tox.ini * Python 3: replace usage of the types module * Python 3: only decode subprocess stdout on py2 * Python 3: replace exec with six.exec\_() * Python 3: Fix absolute import * Python 3: Fix basic py3 issues * [Trivial] Fix too many arguments for format string * Reorder releasenotes and increase toctree depth * Updated from global requirements 3.0.0.0b1 --------- * Updated from global requirements * RabbitMQ heartbeats for consumer threads * Change chef installation method * Install murano-agent to pip default location * Updated from global requirements * Allow insecure SSL communications with RabbitMQ * Updated from global requirements * Restores SIGPIPE on script processes * Update reno for stable/mitaka 2.0.0.0rc1 ---------- * Adds RMQ reconnection on first timeout after EP run 2.0.0.0b3 --------- * Updated from global requirements * Updated from global requirements * Enable pep8 to check files in directory tools * Updated from global requirements * Updated from global requirements * Updated from global requirements * Updated from global requirements * Deleted unused modules from requirements.txt * Updated from global requirements * Remove openstack-common.conf * Updated from global requirements * Fix Mutable defalut argument 2.0.0.0b2 --------- * Updated from global requirements * Clean flake8 ignore * Updated from global requirements * Replace deprecated library function os.popen() with subprocess * Updated from global requirements * Updated from global requirements * Replace unicode with six.text\_type * py26 is no longer supported by Infra's CI * Drop MANIFEST.in - it's not needed with PBR * Updated from global requirements * Pass environment variables of proxy to tox * Ensure murano-agent starts on boot on debian-based images * Remove version from setup.cfg * Replace stackforge with openstack 2.0.0.0b1 --------- * Drop bunch dependency * Add reno for RElease NOtes * Add Berkshelf support * Remove hardcoded destinations for puppet/chef processing engine * Remove unnecessary rmtree call * Add dynamic result message routing * Open Mitaka development 1.0.0 ----- * Update the gitignore file to ignore .swp * Update the murano agent README * NuGet.exe was removed from the repo * Adding svn for file download 1.0.0.0rc1 ---------- * Activate pep8 check that \_ is imported 1.0.0.0b3 --------- * Remove openstack.common package * Use timeutils from oslo\_utils * Switch to the oslo.log library 1.0.0.0b2 --------- * Puppet default execution involves the definition of none modules. The Puppet executor has been modified to consider if the recipe is empty * Update Ubuntu-based image build documentation * Switch to oslo.service * Chef and Puppet elements integration into Murano-agent 1.0.0.0b1 --------- * Update version for Liberty * ignore testr output directory * Update requirements 1.0.0a0 ------- * Add Murano Agent for Windows * Add murano-agent DIB element for Debian * Drop use of 'oslo' namespace package * Update README file * Folder Not Found with Git Downloadable File * Open Liberty development 2015.1.0rc1 ----------- * Update from global requirements * Increment max FormatVersion * [DIB] Fix repository names in murano-agent elements * Update .gitreview file to reflect repo rename * Fixes file placement * Support for Configuration Language: Puppet * Fixes image building, CI tests and requirements * Support for Configuration Language: Chef * Support non-application scripts in the execution plan * Support for Configuration Language. File Downloading 2015.1.0b3 ---------- * Fix typo in files\_manager.py 2015.1.0b2 ---------- * Remove existing config * Self-sufficient DIB elements * Fix 'is' statement to 'in' in Murano Agent 2015.1.0b1 ---------- * Workflow documentation is now in infra-manual * Unicode characters handling * Fix use of the oslo-config-generator * Remove muranoagent.conf.sample * Remove generate\_samlple.sh tool from the project * Use oslo.config generator * Open Kilo development 2014.2 ------ * Updated from global requirements * Windows agent was moved to another repo * Fix requirement for semver * Fix murano agent component name * Add dib element to build an image with murano-agent * Make sure the name in setup.cfg is murano-agent not muranoagent 2014.2.b3 --------- * Handle version information * Enable H301, H302, H304, H306, H231, H233 * Run tests with testrepository * Make improvements in logging * Add sample config and it's checker * Update openstack-common * Add virtual environment installation scripts * Remove hardcoded version 2014.2.b2 --------- * Updated from global requirements * Setup doc build and test infrastructure 2014.2.b1 --------- * Extract main python client to the top * Send message\_id as property 0.5.0 ----- * Correct murano-agent reference to message headers * Removed dependency from kombu.five * Merged in murano-common * Update README with actual info * Bug: 1263727 (agent\_template requires parameter) 0.4 --- * Cherry-picked changes from release-0.3 * Update requirements to match havana's ones * Add C demo agent * Python Agent initial release * Cherry-pick following commit from release-0.2 * Project retargeted to .NET 4.0CP. Fixed incorrect warning message in logs * Cherry-pick following change-ids from release-0.2 * Handling of arrays and dictionaries as input parameters, arrays as a result * Wrong AcceptablePolicyErrors default for SSL in agent * typo * Added support for RabbitMQ SSL-secured connections 0.1 --- * KEERO-316 - Fix all occurrences of old names (keero, glazier) * Removed all projects except Glazier Agent * Small fixes for unit tests * Fixed issue with length of new name * Fixed small issue * Fixed issue with names * Fixed issue with names * Fixed issue with names * Fixed issue with names * Fixed issue with names * Fixed issue with names * Fixed issue with names * Fixed small issue with new names * Fixed issue with horizon component installation * Fixed issue with horizon component installation * Fixed issue with horizon component installation * Finished converting API Specification * Fixed small issue with setup.py * Fixed issue with renaming of the tabula component * Fixed issue with renaming of the tabula component * Added part of API Specification * Tabula renamed to dashboard * Tabula renamed to dashboard * Finished documentation for API * Finished documentation for API * Renamed Portas to API * Renamed Portas to API * Added tox for webUI tests * Added license to documentation of Portas Client * Small fix * Fixed api interface names to environments * Fixed api interface names to environments * Renamed and licensed python-glazierclient * Fixed api interface names to environments * Fixed api interface names to environments * Renamed documentation project * Fixed licenses for tabula and tests. Fixed name of tabula project * Fixed licenses for tabula and tests. Fixed name of tabula project * Fixed a few small issues * Pass all RabbitMQ settings from conductor to Agent * Initialization of tox for conductor and portas. Add new webUI automated tests * Licenses added * A lot of changes were made * Issue with figures * Main Documentation Project * Fixed ignore file for python-portasclient * Documentation for UI * Documentation for Python PortasClient * Forgot man pages * Documentation for Portas Project * Send token when deleting environment * Fixed https://mirantis.jira.com/browse/KEERO-227 * Fixed issue with sessions * Fixed issue with sessions * Experiments * Experiments * Experiments * Experiments * Experiments * Add logging to WebUI * Add initial files for unit tests * Fixed issues with sessions Added logging * Added unit tests for client. Coverage 66% * Rename RabbitMQ username field Removed use\_ssl option from settings * Fix running install\_venv.py * Updated python-portasclient * PEP8 compliance * Fixed unit tests * Added ability to add services to environment * bug fix * bug fix * Fixed index bug * Finalize UI * Finalize UI * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Fix PEP8 errors * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Fix issue with statuses * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Experiments * Fixed issue with sessions * Naming conventions: use name instead of id for instance names * Heat auto-discovery, keero-linux-keys -> keero-keys * Experiments with UI * typo * Scoped tokens * Experiments with UI * Experiments with UI * Experiments with UI * Experiments with UI * Experiments with UI * Experiments with UI * Experiments with UI * Fix issue for result of deleted environments * Fix merge issue * Merged * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fix name of the variable * Fixed small issue * Send token when deleting environment * Removed unneeded binding * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Added tabs for services * forgotten file * Fixed issue with activeDirectory deletion * Add support for reports filtering * Added tabs for services * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Fixed small issue * Added dropdown list with list of services * Added initial version of tabs for services * Added initial version of tabs for services * Added initial version of tabs for services * Fixed issues with templates * Fixed issue with installation * Fixed issue with installation * PEP-8 * Fixed issue with incorrect import * logging and bug-fixes * fixed VM initialization script * Evironment/Units deletion, bug-fixes * Fixed UI issues * Remove service deletion button * Finished installable UI * Removed old code * Naming conventions changed * Updated OpenStack Common (Fixed issue with notifier package) * Use Heat REST API instead of command-line * Added support for setup.py Added localization and documentation skeletons PEP8 Fixes, optimized imports * #KEERO-222 Remove random part of unit name * Send Env to Conductor for deletion * Hot fix for WebUI tests * Fixed WebUI tests. Added new tests * #KEERO-220 Send X-Auth-Token to Conductor * Added initial unit tests for RestAPI service * Fixed all pep8 * Fixed automated tests for web UI * Fixed automated tests for WebUI. Added class Page with simple objects * Code to start\stop keero components using devstack functions * Fixed: changed the run mode for install venv script * Added deployment script for automated tests * All Cloudbase-Init plugins disabled except UserDataPlugin * Userdata script updated to support computer renaming functionality * Entry point script renamed 2d27f4f5054f34982ed67da2bf4b35c8ac1558d3 * Issues #195 and #199 * README and guide for conductor * Fix and unit test for issue: https://mirantis.jira.com/browse/KEERO-219 * Added unit tests for REST API client. Fixed pep8 * New devstack scripts added * Old devstack scripts removed * Write-Host replaced by Write-Log * Fixed typo * Sync * Sync * Sync * Cloned horizon and added our dashboard * Removed obsolete code Removed projects: [windc, windcclient] * Added tests for REST API. Fixed issues with Web UI * Added tests for REST API. Fixed issues with Web UI * Merged iteration3 branch to master. Fixed pep8 * Fixed small issues with UI * Added lst fixes for demo * Fix another issue with environments list * Fix another issue with services * Fix issue with getting list of environments * Added progress bars for services. Fixed few issues for demo * Fix issue with ack on results * Add part of service id to unit name * Add ability to get status for Environments and Sessions * Added password-secure checks for UI, fix usability issues for demo * ExecutionPlanGenerator DSL processor * Updated workflow elements to reflect new name changes and to fix typos * ExecutionPlanGenerator DSL processor * Updated workflow elements to reflect new name changes and to fix typos * Another Issue with sessions * Added progress bar to Web UI. Fixed pep8 errors * Change behaviour of viewing services * Issue with session * No ack is needed when auto\_ack set to True * Resolved issue with reports from orchestration engine * FIx issue with fields created & updated * Fixed issue with logging * Added deploy button for data centers in UI. Fixed templates for services * Queues should be durable * Add debug logging for controllers * Sync before tag * Fixed issue with empty services list * Added new API for Web UI * typos * Fixed length of names * Fixed instance namings * Added WebServer and AD * Workflows, ExecutionPlanGenerator, Reporting, UserData, conductor improvements * Removed obsolete file * Bug with Session * Added Session operations * Added Environments CRUD operations * Issue with deleting Environment * Removed obsolete files * Added initial version for python-portasclient * Issue with port for RabbitMQ * Function updated to return IPv4 addresses only * Typo * Explicit import of module DnsServer added * Function to install IIS added * Code to return DNS listening IPs from DC added * WebServer API Added WebServer API Small refactoring * Fix issues with queues * Added units name generation * Write results from orchestration engine * Active Directory API * Remove obsolete service table * Enable session deployment * Reports from orchestration engine Added ability to store and expose reports from orchestration engine * Cleaned up API * Added support for reading messages from RabbitMQ asynchronously * Typo * userdata.py fixed * Finished Task KEERO-111. Added base UI tests * Hot fix: Fixed pep8 for Dashboard * Finished Task: KEERO-117. Added new UI wizard for Create Services Action * Userdata plugin with minimal MIME support added * User data sample file added * Extra functions moved to NotCoreFunctions.ps1 file in order to remove them in the future * Functions to work with Base64 strings added * Functions to work with Zip files added * Modified files from cloudbase-init added * Fixed pep8. Fixed deployment script * Added support for session checking * Most part of Session API * Removed obsolete code * Added new Session model and migration Fixed issues with previous models * Initial conductor implementation * Added deployment script and automated tests * Small PEP8 fixes * Fixed small issues with parameters. It is required fix * Added remove method for environments Also slightly updated routes table * Finished environments api * Only environments from same tenant as users should be shown * Remove unnecessary blocks of code * When new DC is adding tenant\_id is added as param * Fix issues with context * Moved utils.py from WindDC * Small changes to .gitignore Removed global .gitignore Added .gitignore to WindowsAgent project * Update added files * Added support for keystone-auth * Updated initial version of portas-api * Initial version of portas-api * Simple function to update agent config added * Simple function for working with templates added * Function to retrieve meta data opject from config drive added * localrc updated * Files to automate devstack installation added * Fixed small issues with WebUI * asd * test.commit * test.commit * Log functions updated * Stop-Execution modified * Removed obsole line * Removed obsolete file Added .gitignore file * Added reference JSON for Active Directory * Fixed urls for dashboard * Fixed Web UI for demo * Files removed * Windows PowerShell module added * Unattended installation files added * Execution plan files added * windc iteration2 * Added WebUI for correct configuration of new service AD * Resolved issue with datacenter id * Resolved issue with datacenter id * Fixed many small issues * Fixed typo * Fixed KEERO-89 * Fixed issue with data centers * Added services functions to client. Need to be tested * [KEERO-83] Windows Agent: Ability to reboot machine after execution plan is executed * [KEERO-83] Windows Agent: Typo fixes + sample values in config * [KEERO-83] Windows Agent initial implementation * Added operations for chef. They might be remove if we decide to not use chef * Fixed small issues * Fixed KEERO-85 * Fixed issue with virtual environment SQLAlchemy library * Added library libsqlite3-dev to virtual environment for windc client * Added new functional to dashboard, fixed small issues * Added windc API client, sync repo with dev box * Added new files * Updated design. Removed extra code * 1. Added support of CloudFormation templates. Made a simple interface to build template. Stan can work here to redesign template.py 2. Added calls of drivers. Now heat is called from cmd instead of client. Should be rewritten. 3. ActiveDirectory makes a static template. Need to rewrite this with working with actual parameters * Added additional fields for Domain Controller * Added simple form for configuration Domen Controllers and IIS Servers * Fixed small problems with links and titles on pages * Fixed small problems with links and titles on pages * Added initial project for horizon dashboard * 1. Added builders support. Each builder is a class dynamically loaded from ./windc/core/builders folder. The class name should be the same as module file name. 2. Updated core/api.py to support datacenter and service creation with extra parameters which are not defined by model explicitly. 3. Added event based approach for the windows environment change. Now when user submits a request to API the core updates database and initiates a new event which defined scope (datacenter, service, VM) and action (add, modify, delete). This event and data will be iterated over all registered builders. Each builder can use this event and data to plan some modification * 1. Fixed issue with main file start ./bin/windc-api 2. Added router to Route /datacenters/ and /services/ URLs 3. Added stubs for windc/core/api. 4. Fixed start-up process for service ------------------------------------------------- Now it is working service which will reply for curl http://localhost:8181/tenant\_id/datacenters/ curl http://localhost:8181/tenant\_id/datacenters/dc\_id/services curl http://localhost:8181/tenant\_id/datacenters/dc\_id/services/service\_id * Initial version of the Windows DataCenter project. It is openstak-skeleton based * Unattended files added * Initial empty repository ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/HACKING.rst0000664000175000017500000000017000000000000015734 0ustar00zuulzuul00000000000000Style Commandments ================== Read the OpenStack Style Commandments https://docs.openstack.org/hacking/latest/ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/LICENSE0000664000175000017500000002363700000000000015160 0ustar00zuulzuul00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2488828 murano-agent-9.0.0/PKG-INFO0000664000175000017500000000612100000000000015235 0ustar00zuulzuul00000000000000Metadata-Version: 1.2 Name: murano-agent Version: 9.0.0 Summary: Python Murano Agent Home-page: https://docs.openstack.org/murano/latest/ Author: OpenStack Author-email: openstack-discuss@lists.openstack.org License: Apache License, Version 2.0 Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/murano-agent.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Murano Agent ============ Murano Agent is a VM-side guest agent that accepts commands from Murano engine and executes them. Image building using DiskImage-Builder -------------------------------------- Folder, named *contrib/elements* contains `diskimage-builder `_ elements to build an image which contains the Murano Agent required to use Murano. Ubuntu based image containing the agent can be built and uploaded to Glance with the following commands: :: $ git clone https://opendev.org/openstack/diskimage-builder.git $ git clone https://opendev.org/openstack/murano-agent.git $ export ELEMENTS_PATH=murano-agent/contrib/elements $ export DIB_CLOUD_INIT_DATASOURCES=OpenStack $ diskimage-builder/bin/disk-image-create vm ubuntu \ murano-agent -o ubuntu-murano-agent.qcow2 $ openstack image create ubuntu-murano --disk-format qcow2 --container-format bare --file ubuntu-murano-agent.qcow2 \ --property murano_image_info='{"title": "Ubuntu for Murano", "type": "linux"}' Project Resources ----------------- Project status, bugs, and blueprints are tracked on Launchpad: https://launchpad.net/murano Developer documentation can be found here: https://docs.openstack.org/murano/latest/ Additional resources are linked from the project wiki page: https://wiki.openstack.org/wiki/Murano License ------- Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Requires-Python: >=3.6 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/README.rst0000664000175000017500000000327400000000000015635 0ustar00zuulzuul00000000000000======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/murano-agent.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Murano Agent ============ Murano Agent is a VM-side guest agent that accepts commands from Murano engine and executes them. Image building using DiskImage-Builder -------------------------------------- Folder, named *contrib/elements* contains `diskimage-builder `_ elements to build an image which contains the Murano Agent required to use Murano. Ubuntu based image containing the agent can be built and uploaded to Glance with the following commands: :: $ git clone https://opendev.org/openstack/diskimage-builder.git $ git clone https://opendev.org/openstack/murano-agent.git $ export ELEMENTS_PATH=murano-agent/contrib/elements $ export DIB_CLOUD_INIT_DATASOURCES=OpenStack $ diskimage-builder/bin/disk-image-create vm ubuntu \ murano-agent -o ubuntu-murano-agent.qcow2 $ openstack image create ubuntu-murano --disk-format qcow2 --container-format bare --file ubuntu-murano-agent.qcow2 \ --property murano_image_info='{"title": "Ubuntu for Murano", "type": "linux"}' Project Resources ----------------- Project status, bugs, and blueprints are tracked on Launchpad: https://launchpad.net/murano Developer documentation can be found here: https://docs.openstack.org/murano/latest/ Additional resources are linked from the project wiki page: https://wiki.openstack.org/wiki/Murano License ------- Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1648641201.220883 murano-agent-9.0.0/contrib/0000775000175000017500000000000000000000000015600 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2288828 murano-agent-9.0.0/contrib/c-demo-agent/0000775000175000017500000000000000000000000020040 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/Makefile0000664000175000017500000000201600000000000021477 0ustar00zuulzuul00000000000000# Makefile for murano agent CFLAGS= -Wall default_target: all all: agent-binary producer-binary # NOTE: Use this if RabbitMQ needs to be linked in as a dynamic library #agent-binary: murano-agent.o lcfg_static.o utils.o # gcc -o murano-agent murano-agent.o lcfg_static.o utils.o -lrabbitmq -lrt agent-binary: murano-agent.o lcfg_static.o utils.o librabbitmq.a gcc $(CFLAGS) -o murano-agent murano-agent.o lcfg_static.o utils.o -L. -lrabbitmq -lrt # NOTE: Use this if RabbitMQ needs to be linked in as a dynamic library #producer-binary: producer.o utils.o # gcc -o producer producer.o utils.o -lrabbitmq -lrt producer-binary: producer.o utils.o librabbitmq.a gcc $(CFLAGS) -o producer producer.o utils.o -L. -lrabbitmq -lrt murano-agent.o: murano-agent.c gcc $(CFLAGS) -c -I. -fPIC murano-agent.c producer.o: producer.c gcc $(CFLAGS) -c -I. -fPIC producer.c lcfg_static.o: lcfg_static.c gcc $(CFLAGS) -c -fPIC lcfg_static.c utils.o: utils.c gcc $(CFLAGS) -c -I. -fPIC utils.c clean: rm -f *.o murano-agent producer ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/Readme0000664000175000017500000000322200000000000021157 0ustar00zuulzuul00000000000000This is a demo implementation of Murano agent. === The scenario === Effectively the agent only connects to an AMQP queue using properties from the configuration file, consumes all the messages from the queue, logs them and puts result messages into a result queue. Result messages are just stubs signaling success back to the calling application. === Building binaries === Build process has been tested on Ubuntu 13.04 only for x86_64 architecture. Note that the distribution contains RabbitMQ client pre-built as a static library. It gets linked with demo agent object files statically. It was done to eliminate the need to build and install RabbitMQ client library separately in case of using Ubuntu 64 bit. In order to build demo agent for embedded operating systems based on BusyBox technology (such as Cirros) refer to Buildroot toolkit (http://buildroot.uclibc.org/). To build agent binary: make agent-binary To build test producer binary: make prodcer-binary To build both binaries: make To clean up the source directory: make clean === Usage === To run agent: ./murano-agent : Refer to murano-agent.conf.example file to find out what configuration properties are possible. : Path to log file which agent writes the messages into. To run test message producer: ./producer : RabbitMQ server host for the producer to connect to. : RabbitMQ server port for the producer to connect to. : Message rate at which the producer sends messages (delay in seconds between messages). : A number of messages the producer should send. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/amqp.h0000664000175000017500000024636100000000000021163 0ustar00zuulzuul00000000000000/* vim:set ft=c ts=2 sw=2 sts=2 et cindent: */ /** \file */ /* * ***** BEGIN LICENSE BLOCK ***** * Version: MIT * * Portions created by Alan Antonuk are Copyright (c) 2012-2013 * Alan Antonuk. All Rights Reserved. * * Portions created by VMware are Copyright (c) 2007-2012 VMware, Inc. * All Rights Reserved. * * Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010 * VMware, Inc. and Tony Garnock-Jones. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * ***** END LICENSE BLOCK ***** */ #ifndef AMQP_H #define AMQP_H /** \cond HIDE_FROM_DOXYGEN */ #ifdef __cplusplus #define AMQP_BEGIN_DECLS extern "C" { #define AMQP_END_DECLS } #else #define AMQP_BEGIN_DECLS #define AMQP_END_DECLS #endif /* * \internal * Important API decorators: * AMQP_PUBLIC_FUNCTION - a public API function * AMQP_PUBLIC_VARIABLE - a public API external variable * AMQP_CALL - calling convension (used on Win32) */ #if defined(_WIN32) && defined(_MSC_VER) # if defined(AMQP_BUILD) && !defined(AMQP_STATIC) # define AMQP_PUBLIC_FUNCTION __declspec(dllexport) # define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern # else # define AMQP_PUBLIC_FUNCTION # if !defined(AMQP_STATIC) # define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern # else # define AMQP_PUBLIC_VARIABLE extern # endif # endif # define AMQP_CALL __cdecl #elif defined(_WIN32) && defined(__BORLANDC__) # if defined(AMQP_BUILD) && !defined(AMQP_STATIC) # define AMQP_PUBLIC_FUNCTION __declspec(dllexport) # define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern # else # define AMQP_PUBLIC_FUNCTION # if !defined(AMQP_STATIC) # define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern # else # define AMQP_PUBLIC_VARIABLE extern # endif # endif # define AMQP_CALL __cdecl #elif defined(_WIN32) && defined(__MINGW32__) # if defined(AMQP_BUILD) && !defined(AMQP_STATIC) # define AMQP_PUBLIC_FUNCTION __declspec(dllexport) # define AMQP_PUBLIC_VARIABLE __declspec(dllexport) extern # else # define AMQP_PUBLIC_FUNCTION # if !defined(AMQP_STATIC) # define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern # else # define AMQP_PUBLIC_VARIABLE extern # endif # endif # define AMQP_CALL __cdecl #elif defined(_WIN32) && defined(__CYGWIN__) # if defined(AMQP_BUILD) && !defined(AMQP_STATIC) # define AMQP_PUBLIC_FUNCTION __declspec(dllexport) # define AMQP_PUBLIC_VARIABLE __declspec(dllexport) # else # define AMQP_PUBLIC_FUNCTION # if !defined(AMQP_STATIC) # define AMQP_PUBLIC_VARIABLE __declspec(dllimport) extern # else # define AMQP_PUBLIC_VARIABLE extern # endif # endif # define AMQP_CALL __cdecl #elif defined(__GNUC__) && __GNUC__ >= 4 # include # define AMQP_PUBLIC_FUNCTION \ __attribute__ ((visibility ("default"))) # define AMQP_PUBLIC_VARIABLE \ __attribute__ ((visibility ("default"))) extern # define AMQP_CALL #else # define AMQP_PUBLIC_FUNCTION # define AMQP_PUBLIC_VARIABLE extern # define AMQP_CALL #endif #if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1) # define AMQP_DEPRECATED(function) \ function __attribute__ ((__deprecated__)) #elif defined(_MSC_VER) # define AMQP_DEPRECATED(function) \ __declspec(deprecated) function #else # define AMQP_DEPRECATED(function) #endif /* Define ssize_t on Win32/64 platforms See: http://lists.cs.uiuc.edu/pipermail/llvmdev/2010-April/030649.html for details */ #if !defined(_W64) #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 #define _W64 __w64 #else #define _W64 #endif #endif #ifdef _MSC_VER #ifdef _WIN64 typedef __int64 ssize_t; #else typedef _W64 int ssize_t; #endif #endif /** \endcond */ #include #include struct timeval; AMQP_BEGIN_DECLS /** * \def AMQP_VERSION_MAJOR * * Major library version number compile-time constant * * The major version is incremented when backwards incompatible API changes * are made. * * \sa AMQP_VERSION, AMQP_VERSION_STRING * * \since v0.4.0 */ /** * \def AMQP_VERSION_MINOR * * Minor library version number compile-time constant * * The minor version is incremented when new APIs are added. Existing APIs * are left alone. * * \sa AMQP_VERSION, AMQP_VERSION_STRING * * \since v0.4.0 */ /** * \def AMQP_VERSION_PATCH * * Patch library version number compile-time constant * * The patch version is incremented when library code changes, but the API * is not changed. * * \sa AMQP_VERSION, AMQP_VERSION_STRING * * \since v0.4.0 */ /** * \def AMQP_VERSION_IS_RELEASE * * Version constant set to 1 for tagged release, 0 otherwise * * NOTE: versions that are not tagged releases are not guaranteed to be API/ABI * compatible with older releases, and may change commit-to-commit. * * \sa AMQP_VERSION, AMQP_VERSION_STRING * * \since v0.4.0 */ /* * Developer note: when changing these, be sure to update SOVERSION constants * in CMakeLists.txt and configure.ac */ #define AMQP_VERSION_MAJOR 0 #define AMQP_VERSION_MINOR 4 #define AMQP_VERSION_PATCH 1 #define AMQP_VERSION_IS_RELEASE 1 /** * \def AMQP_VERSION * * Packed version number * * AMQP_VERSION is a 4-byte unsigned integer with the most significant byte * set to AMQP_VERSION_MAJOR, the second most significant byte set to * AMQP_VERSION_MINOR, third most significant byte set to AMQP_VERSION_PATCH, * and the lowest byte set to AMQP_VERSION_IS_RELEASE. * * For example version 2.3.4 which is released version would be encoded as * 0x02030401 * * \sa amqp_version_number() AMQP_VERSION_MAJOR, AMQP_VERSION_MINOR, * AMQP_VERSION_PATCH, AMQP_VERSION_IS_RELEASE * * \since v0.4.0 */ #define AMQP_VERSION ((AMQP_VERSION_MAJOR << 24) | \ (AMQP_VERSION_MINOR << 16) | \ (AMQP_VERSION_PATCH << 8) | \ (AMQP_VERSION_IS_RELEASE)) /** \cond HIDE_FROM_DOXYGEN */ #define AMQ_STRINGIFY(s) AMQ_STRINGIFY_HELPER(s) #define AMQ_STRINGIFY_HELPER(s) #s #define AMQ_VERSION_STRING AMQ_STRINGIFY(AMQP_VERSION_MAJOR) "." \ AMQ_STRINGIFY(AMQP_VERSION_MINOR) "." \ AMQ_STRINGIFY(AMQP_VERSION_PATCH) /** \endcond */ /** * \def AMQP_VERSION_STRING * * Version string compile-time constant * * Non-released versions of the library will have "-pre" appended to the * version string * * \sa amqp_version() * * \since v0.4.0 */ #if AMQP_VERSION_IS_RELEASE # define AMQP_VERSION_STRING AMQ_VERSION_STRING #else # define AMQP_VERSION_STRING AMQ_VERSION_STRING "-pre" #endif /** * Returns the rabbitmq-c version as a packed integer. * * See \ref AMQP_VERSION * * \return packed 32-bit integer representing version of library at runtime * * \sa AMQP_VERSION, amqp_version() * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION uint32_t AMQP_CALL amqp_version_number(void); /** * Returns the rabbitmq-c version as a string. * * See \ref AMQP_VERSION_STRING * * \return a statically allocated string describing the version of rabbitmq-c. * * \sa amqp_version_number(), AMQP_VERSION_STRING, AMQP_VERSION * * \since v0.1 */ AMQP_PUBLIC_FUNCTION char const * AMQP_CALL amqp_version(void); /** * \def AMQP_DEFAULT_FRAME_SIZE * * Default frame size (128Kb) * * \sa amqp_login(), amqp_login_with_properties() * * \since v0.4.0 */ #define AMQP_DEFAULT_FRAME_SIZE 131072 /** * \def AMQP_DEFAULT_MAX_CHANNELS * * Default maximum number of channels (0, no limit) * * \sa amqp_login(), amqp_login_with_properties() * * \since v0.4.0 */ #define AMQP_DEFAULT_MAX_CHANNELS 0 /** * \def AMQP_DEFAULT_HEARTBEAT * * Default heartbeat interval (0, heartbeat disabled) * * \sa amqp_login(), amqp_login_with_properties() * * \since v0.4.0 */ #define AMQP_DEFAULT_HEARTBEAT 0 /** * boolean type 0 = false, true otherwise * * \since v0.1 */ typedef int amqp_boolean_t; /** * Method number * * \since v0.1 */ typedef uint32_t amqp_method_number_t; /** * Bitmask for flags * * \since v0.1 */ typedef uint32_t amqp_flags_t; /** * Channel type * * \since v0.1 */ typedef uint16_t amqp_channel_t; /** * Buffer descriptor * * \since v0.1 */ typedef struct amqp_bytes_t_ { size_t len; /**< length of the buffer in bytes */ void *bytes; /**< pointer to the beginning of the buffer */ } amqp_bytes_t; /** * Decimal data type * * \since v0.1 */ typedef struct amqp_decimal_t_ { uint8_t decimals; /**< the location of the decimal point */ uint32_t value; /**< the value before the decimal point is applied */ } amqp_decimal_t; /** * AMQP field table * * An AMQP field table is a set of key-value pairs. * A key is a UTF-8 encoded string up to 128 bytes long, and are not null * terminated. * A value can be one of several different datatypes. \sa amqp_field_value_kind_t * * \sa amqp_table_entry_t * * \since v0.1 */ typedef struct amqp_table_t_ { int num_entries; /**< length of entries array */ struct amqp_table_entry_t_ *entries; /**< an array of table entries */ } amqp_table_t; /** * An AMQP Field Array * * A repeated set of field values, all must be of the same type * * \since v0.1 */ typedef struct amqp_array_t_ { int num_entries; /**< Number of entries in the table */ struct amqp_field_value_t_ *entries; /**< linked list of field values */ } amqp_array_t; /* 0-9 0-9-1 Qpid/Rabbit Type Remarks --------------------------------------------------------------------------- t t Boolean b b Signed 8-bit B Unsigned 8-bit U s Signed 16-bit (A1) u Unsigned 16-bit I I I Signed 32-bit i Unsigned 32-bit L l Signed 64-bit (B) l Unsigned 64-bit f f 32-bit float d d 64-bit float D D D Decimal s Short string (A2) S S S Long string A Nested Array T T T Timestamp (u64) F F F Nested Table V V V Void x Byte array Remarks: A1, A2: Notice how the types **CONFLICT** here. In Qpid and Rabbit, 's' means a signed 16-bit integer; in 0-9-1, it means a short string. B: Notice how the signednesses **CONFLICT** here. In Qpid and Rabbit, 'l' means a signed 64-bit integer; in 0-9-1, it means an unsigned 64-bit integer. I'm going with the Qpid/Rabbit types, where there's a conflict, and the 0-9-1 types otherwise. 0-8 is a subset of 0-9, which is a subset of the other two, so this will work for both 0-8 and 0-9-1 branches of the code. */ /** * A field table value * * \since v0.1 */ typedef struct amqp_field_value_t_ { uint8_t kind; /**< the type of the entry /sa amqp_field_value_kind_t */ union { amqp_boolean_t boolean; /**< boolean type AMQP_FIELD_KIND_BOOLEAN */ int8_t i8; /**< int8_t type AMQP_FIELD_KIND_I8 */ uint8_t u8; /**< uint8_t type AMQP_FIELD_KIND_U8 */ int16_t i16; /**< int16_t type AMQP_FIELD_KIND_I16 */ uint16_t u16; /**< uint16_t type AMQP_FIELD_KIND_U16 */ int32_t i32; /**< int32_t type AMQP_FIELD_KIND_I32 */ uint32_t u32; /**< uint32_t type AMQP_FIELD_KIND_U32 */ int64_t i64; /**< int64_t type AMQP_FIELD_KIND_I64 */ uint64_t u64; /**< uint64_t type AMQP_FIELD_KIND_U64, AMQP_FIELD_KIND_TIMESTAMP */ float f32; /**< float type AMQP_FIELD_KIND_F32 */ double f64; /**< double type AMQP_FIELD_KIND_F64 */ amqp_decimal_t decimal; /**< amqp_decimal_t AMQP_FIELD_KIND_DECIMAL */ amqp_bytes_t bytes; /**< amqp_bytes_t type AMQP_FIELD_KIND_UTF8, AMQP_FIELD_KIND_BYTES */ amqp_table_t table; /**< amqp_table_t type AMQP_FIELD_KIND_TABLE */ amqp_array_t array; /**< amqp_array_t type AMQP_FIELD_KIND_ARRAY */ } value; /**< a union of the value */ } amqp_field_value_t; /** * An entry in a field-table * * \sa amqp_table_encode(), amqp_table_decode(), amqp_table_clone() * * \since v0.1 */ typedef struct amqp_table_entry_t_ { amqp_bytes_t key; /**< the table entry key. Its a null-terminated UTF-8 string, * with a maximum size of 128 bytes */ amqp_field_value_t value; /**< the table entry values */ } amqp_table_entry_t; /** * Field value types * * \since v0.1 */ typedef enum { AMQP_FIELD_KIND_BOOLEAN = 't', /**< boolean type. 0 = false, 1 = true @see amqp_boolean_t */ AMQP_FIELD_KIND_I8 = 'b', /**< 8-bit signed integer, datatype: int8_t */ AMQP_FIELD_KIND_U8 = 'B', /**< 8-bit unsigned integer, datatype: uint8_t */ AMQP_FIELD_KIND_I16 = 's', /**< 16-bit signed integer, datatype: int16_t */ AMQP_FIELD_KIND_U16 = 'u', /**< 16-bit unsigned integer, datatype: uint16_t */ AMQP_FIELD_KIND_I32 = 'I', /**< 32-bit signed integer, datatype: int32_t */ AMQP_FIELD_KIND_U32 = 'i', /**< 32-bit unsigned integer, datatype: uint32_t */ AMQP_FIELD_KIND_I64 = 'l', /**< 64-bit signed integer, datatype: int64_t */ AMQP_FIELD_KIND_U64 = 'L', /**< 64-bit unsigned integer, datatype: uint64_t */ AMQP_FIELD_KIND_F32 = 'f', /**< single-precision floating point value, datatype: float */ AMQP_FIELD_KIND_F64 = 'd', /**< double-precision floating point value, datatype: double */ AMQP_FIELD_KIND_DECIMAL = 'D', /**< amqp-decimal value, datatype: amqp_decimal_t */ AMQP_FIELD_KIND_UTF8 = 'S', /**< UTF-8 null-terminated character string, datatype: amqp_bytes_t */ AMQP_FIELD_KIND_ARRAY = 'A', /**< field array (repeated values of another datatype. datatype: amqp_array_t */ AMQP_FIELD_KIND_TIMESTAMP = 'T',/**< 64-bit timestamp. datatype uint64_t */ AMQP_FIELD_KIND_TABLE = 'F', /**< field table. encapsulates a table inside a table entry. datatype: amqp_table_t */ AMQP_FIELD_KIND_VOID = 'V', /**< empty entry */ AMQP_FIELD_KIND_BYTES = 'x' /**< unformatted byte string, datatype: amqp_bytes_t */ } amqp_field_value_kind_t; /** * A list of allocation blocks * * \since v0.1 */ typedef struct amqp_pool_blocklist_t_ { int num_blocks; /**< Number of blocks in the block list */ void **blocklist; /**< Array of memory blocks */ } amqp_pool_blocklist_t; /** * A memory pool * * \since v0.1 */ typedef struct amqp_pool_t_ { size_t pagesize; /**< the size of the page in bytes. * allocations less than or equal to this size are * allocated in the pages block list * allocations greater than this are allocated in their * own block in the large_blocks block list */ amqp_pool_blocklist_t pages; /**< blocks that are the size of pagesize */ amqp_pool_blocklist_t large_blocks; /**< allocations larger than the pagesize */ int next_page; /**< an index to the next unused page block */ char *alloc_block; /**< pointer to the current allocation block */ size_t alloc_used; /**< number of bytes in the current allocation block that has been used */ } amqp_pool_t; /** * An amqp method * * \since v0.1 */ typedef struct amqp_method_t_ { amqp_method_number_t id; /**< the method id number */ void *decoded; /**< pointer to the decoded method, * cast to the appropriate type to use */ } amqp_method_t; /** * An AMQP frame * * \since v0.1 */ typedef struct amqp_frame_t_ { uint8_t frame_type; /**< frame type. The types: * - AMQP_FRAME_METHOD - use the method union member * - AMQP_FRAME_HEADER - use the properties union member * - AMQP_FRAME_BODY - use the body_fragment union member */ amqp_channel_t channel; /**< the channel the frame was received on */ union { amqp_method_t method; /**< a method, use if frame_type == AMQP_FRAME_METHOD */ struct { uint16_t class_id; /**< the class for the properties */ uint64_t body_size; /**< size of the body in bytes */ void *decoded; /**< the decoded properties */ amqp_bytes_t raw; /**< amqp-encoded properties structure */ } properties; /**< message header, a.k.a., properties, use if frame_type == AMQP_FRAME_HEADER */ amqp_bytes_t body_fragment; /**< a body fragment, use if frame_type == AMQP_FRAME_BODY */ struct { uint8_t transport_high; /**< @internal first byte of handshake */ uint8_t transport_low; /**< @internal second byte of handshake */ uint8_t protocol_version_major; /**< @internal third byte of handshake */ uint8_t protocol_version_minor; /**< @internal fourth byte of handshake */ } protocol_header; /**< Used only when doing the initial handshake with the broker, don't use otherwise */ } payload; /**< the payload of the frame */ } amqp_frame_t; /** * Response type * * \since v0.1 */ typedef enum amqp_response_type_enum_ { AMQP_RESPONSE_NONE = 0, /**< the library got an EOF from the socket */ AMQP_RESPONSE_NORMAL, /**< response normal, the RPC completed successfully */ AMQP_RESPONSE_LIBRARY_EXCEPTION,/**< library error, an error occurred in the library, examine the library_error */ AMQP_RESPONSE_SERVER_EXCEPTION /**< server exception, the broker returned an error, check replay */ } amqp_response_type_enum; /** * Reply from a RPC method on the broker * * \since v0.1 */ typedef struct amqp_rpc_reply_t_ { amqp_response_type_enum reply_type; /**< the reply type: * - AMQP_RESPONSE_NORMAL - the RPC completed successfully * - AMQP_RESPONSE_SERVER_EXCEPTION - the broker returned * an exception, check the reply field * - AMQP_RESPONSE_LIBRARY_EXCEPTION - the library * encountered an error, check the library_error field */ amqp_method_t reply; /**< in case of AMQP_RESPONSE_SERVER_EXCEPTION this * field will be set to the method returned from the broker */ int library_error; /**< in case of AMQP_RESPONSE_LIBRARY_EXCEPTION this * field will be set to an error code. An error * string can be retrieved using amqp_error_string */ } amqp_rpc_reply_t; /** * SASL method type * * \since v0.1 */ typedef enum amqp_sasl_method_enum_ { AMQP_SASL_METHOD_PLAIN = 0 /**< the PLAIN SASL method for authentication to the broker */ } amqp_sasl_method_enum; /** * connection state object * * \since v0.1 */ typedef struct amqp_connection_state_t_ *amqp_connection_state_t; /** * Socket object * * \since v0.4.0 */ typedef struct amqp_socket_t_ amqp_socket_t; /** * Status codes * * \since v0.4.0 */ typedef enum amqp_status_enum_ { AMQP_STATUS_OK = 0x0, /**< Operation successful */ AMQP_STATUS_NO_MEMORY = -0x0001, /**< Memory allocation failed */ AMQP_STATUS_BAD_AMQP_DATA = -0x0002, /**< Incorrect or corrupt data was received from the broker. This is a protocol error. */ AMQP_STATUS_UNKNOWN_CLASS = -0x0003, /**< An unknown AMQP class was received. This is a protocol error. */ AMQP_STATUS_UNKNOWN_METHOD = -0x0004, /**< An unknown AMQP method was received. This is a protocol error. */ AMQP_STATUS_HOSTNAME_RESOLUTION_FAILED= -0x0005, /**< Unable to resolve the * hostname */ AMQP_STATUS_INCOMPATIBLE_AMQP_VERSION = -0x0006, /**< The broker advertised an incompaible AMQP version */ AMQP_STATUS_CONNECTION_CLOSED = -0x0007, /**< The connection to the broker has been closed */ AMQP_STATUS_BAD_URL = -0x0008, /**< malformed AMQP URL */ AMQP_STATUS_SOCKET_ERROR = -0x0009, /**< A socket error occurred */ AMQP_STATUS_INVALID_PARAMETER = -0x000A, /**< An invalid parameter was passed into the function */ AMQP_STATUS_TABLE_TOO_BIG = -0x000B, /**< The amqp_table_t object cannot be serialized because the output buffer is too small */ AMQP_STATUS_WRONG_METHOD = -0x000C, /**< The wrong method was received */ AMQP_STATUS_TIMEOUT = -0x000D, /**< Operation timed out */ AMQP_STATUS_TIMER_FAILURE = -0x000E, /**< The underlying system timer facility failed */ AMQP_STATUS_HEARTBEAT_TIMEOUT = -0x000F, /**< Timed out waiting for heartbeat */ AMQP_STATUS_UNEXPECTED_STATE = -0x0010, /**< Unexpected protocol state */ AMQP_STATUS_TCP_ERROR = -0x0100, /**< A generic TCP error occurred */ AMQP_STATUS_TCP_SOCKETLIB_INIT_ERROR = -0x0101, /**< An error occurred trying to initialize the socket library*/ AMQP_STATUS_SSL_ERROR = -0x0200, /**< A generic SSL error occurred. */ AMQP_STATUS_SSL_HOSTNAME_VERIFY_FAILED= -0x0201, /**< SSL validation of hostname against peer certificate failed */ AMQP_STATUS_SSL_PEER_VERIFY_FAILED = -0x0202, /**< SSL validation of peer certificate failed. */ AMQP_STATUS_SSL_CONNECTION_FAILED = -0x0203 /**< SSL handshake failed. */ } amqp_status_enum; AMQP_END_DECLS #include AMQP_BEGIN_DECLS /** * Empty bytes structure * * \since v0.2 */ AMQP_PUBLIC_VARIABLE const amqp_bytes_t amqp_empty_bytes; /** * Empty table structure * * \since v0.2 */ AMQP_PUBLIC_VARIABLE const amqp_table_t amqp_empty_table; /** * Empty table array structure * * \since v0.2 */ AMQP_PUBLIC_VARIABLE const amqp_array_t amqp_empty_array; /* Compatibility macros for the above, to avoid the need to update code written against earlier versions of librabbitmq. */ /** * \def AMQP_EMPTY_BYTES * * Deprecated, use \ref amqp_empty_bytes instead * * \deprecated use \ref amqp_empty_bytes instead * * \since v0.1 */ #define AMQP_EMPTY_BYTES amqp_empty_bytes /** * \def AMQP_EMPTY_TABLE * * Deprecated, use \ref amqp_empty_table instead * * \deprecated use \ref amqp_empty_table instead * * \since v0.1 */ #define AMQP_EMPTY_TABLE amqp_empty_table /** * \def AMQP_EMPTY_ARRAY * * Deprecated, use \ref amqp_empty_array instead * * \deprecated use \ref amqp_empty_array instead * * \since v0.1 */ #define AMQP_EMPTY_ARRAY amqp_empty_array /** * Initializes an amqp_pool_t memory allocation pool for use * * Readies an allocation pool for use. An amqp_pool_t * must be initialized before use * * \param [in] pool the amqp_pool_t structure to initialize. * Calling this function on a pool a pool that has * already been initialized will result in undefined * behavior * \param [in] pagesize the unit size that the pool will allocate * memory chunks in. Anything allocated against the pool * with a requested size will be carved out of a block * this size. Allocations larger than this will be * allocated individually * * \sa recycle_amqp_pool(), empty_amqp_pool(), amqp_pool_alloc(), * amqp_pool_alloc_bytes(), amqp_pool_t * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL init_amqp_pool(amqp_pool_t *pool, size_t pagesize); /** * Recycles an amqp_pool_t memory allocation pool * * Recycles the space allocate by the pool * * This invalidates all allocations made against the pool before this call is * made, any use of any allocations made before recycle_amqp_pool() is called * will result in undefined behavior. * * Note: this may or may not release memory, to force memory to be released * call empty_amqp_pool(). * * \param [in] pool the amqp_pool_t to recycle * * \sa recycle_amqp_pool(), empty_amqp_pool(), amqp_pool_alloc(), * amqp_pool_alloc_bytes() * * \since v0.1 * */ AMQP_PUBLIC_FUNCTION void AMQP_CALL recycle_amqp_pool(amqp_pool_t *pool); /** * Empties an amqp memory pool * * Releases all memory associated with an allocation pool * * \param [in] pool the amqp_pool_t to empty * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL empty_amqp_pool(amqp_pool_t *pool); /** * Allocates a block of memory from an amqp_pool_t memory pool * * Memory will be aligned on a 8-byte boundary. If a 0-length allocation is * requested, a NULL pointer will be returned. * * \param [in] pool the allocation pool to allocate the memory from * \param [in] amount the size of the allocation in bytes. * \return a pointer to the memory block, or NULL if the allocation cannot * be satisfied. * * \sa init_amqp_pool(), recycle_amqp_pool(), empty_amqp_pool(), * amqp_pool_alloc_bytes() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void * AMQP_CALL amqp_pool_alloc(amqp_pool_t *pool, size_t amount); /** * Allocates a block of memory from an amqp_pool_t to an amqp_bytes_t * * Memory will be aligned on a 8-byte boundary. If a 0-length allocation is * requested, output.bytes = NULL. * * \param [in] pool the allocation pool to allocate the memory from * \param [in] amount the size of the allocation in bytes * \param [in] output the location to store the pointer. On success * output.bytes will be set to the beginning of the buffer * output.len will be set to amount * On error output.bytes will be set to NULL and output.len * set to 0 * * \sa init_amqp_pool(), recycle_amqp_pool(), empty_amqp_pool(), * amqp_pool_alloc() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_pool_alloc_bytes(amqp_pool_t *pool, size_t amount, amqp_bytes_t *output); /** * Wraps a c string in an amqp_bytes_t * * Takes a string, calculates its length and creates an * amqp_bytes_t that points to it. The string is not duplicated. * * For a given input cstr, The amqp_bytes_t output.bytes is the * same as cstr, output.len is the length of the string not including * the \0 terminator * * This function uses strlen() internally so cstr must be properly * terminated * * \param [in] cstr the c string to wrap * \return an amqp_bytes_t that describes the string * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_bytes_t AMQP_CALL amqp_cstring_bytes(char const *cstr); /** * Duplicates an amqp_bytes_t buffer. * * The buffer is cloned and the contents copied. * * The memory associated with the output is allocated * with amqp_bytes_malloc() and should be freed with * amqp_bytes_free() * * \param [in] src * \return a clone of the src * * \sa amqp_bytes_free(), amqp_bytes_malloc() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_bytes_t AMQP_CALL amqp_bytes_malloc_dup(amqp_bytes_t src); /** * Allocates a amqp_bytes_t buffer * * Creates an amqp_bytes_t buffer of the specified amount, the buffer should be * freed using amqp_bytes_free() * * \param [in] amount the size of the buffer in bytes * \returns an amqp_bytes_t with amount bytes allocated. * output.bytes will be set to NULL on error * * \sa amqp_bytes_free(), amqp_bytes_malloc_dup() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_bytes_t AMQP_CALL amqp_bytes_malloc(size_t amount); /** * Frees an amqp_bytes_t buffer * * Frees a buffer allocated with amqp_bytes_malloc() or amqp_bytes_malloc_dup() * * Calling amqp_bytes_free on buffers not allocated with one * of those two functions will result in undefined behavior * * \param [in] bytes the buffer to free * * \sa amqp_bytes_malloc(), amqp_bytes_malloc_dup() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_bytes_free(amqp_bytes_t bytes); /** * Allocate and initialize a new amqp_connection_state_t object * * amqp_connection_state_t objects created with this function * should be freed with amqp_destroy_connection() * * \returns an opaque pointer on success, NULL or 0 on failure. * * \sa amqp_destroy_connection() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_connection_state_t AMQP_CALL amqp_new_connection(void); /** * Get the underlying socket descriptor for the connection * * \warning Use the socket returned from this function carefully, incorrect use * of the socket outside of the library will lead to undefined behavior. * Additionally rabbitmq-c may use the socket differently version-to-version, * what may work in one version, may break in the next version. Be sure to * throughly test any applications that use the socket returned by this * function especially when using a newer version of rabbitmq-c * * \param [in] state the connection object * \returns the socket descriptor if one has been set, -1 otherwise * * \sa amqp_tcp_socket_new(), amqp_ssl_socket_new(), amqp_socket_open() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_get_sockfd(amqp_connection_state_t state); /** * Deprecated, use amqp_tcp_socket_new() or amqp_ssl_socket_new() * * \deprecated Use amqp_tcp_socket_new() or amqp_ssl_socket_new() * * Sets the socket descriptor associated with the connection. The socket * should be connected to a broker, and should not be read to or written from * before calling this function. A socket descriptor can be created and opened * using amqp_open_socket() * * \param [in] state the connection object * \param [in] sockfd the socket * * \sa amqp_open_socket(), amqp_tcp_socket_new(), amqp_ssl_socket_new() * * \since v0.1 */ AMQP_DEPRECATED( AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_set_sockfd(amqp_connection_state_t state, int sockfd) ); /** * Tune client side parameters * * \warning This function may call abort() if the connection is in a certain * state. As such it should probably not be called code outside the library. * connection parameters should be specified when calling amqp_login() or * amqp_login_with_properties() * * This function changes channel_max, frame_max, and heartbeat parameters, on * the client side only. It does not try to renegotiate these parameters with * the broker. Using this function will lead to unexpected results. * * \param [in] state the connection object * \param [in] channel_max the maximum number of channels. * The largest this can be is 65535 * \param [in] frame_max the maximum size of an frame. * The smallest this can be is 4096 * The largest this can be is 2147483647 * Unless you know what you're doing the recommended * size is 131072 or 128KB * \param [in] heartbeat the number of seconds between heartbeats * * \return AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. * Possible error codes include: * - AMQP_STATUS_NO_MEMORY memory allocation failed. * - AMQP_STATUS_TIMER_FAILURE the underlying system timer indicated it * failed. * * \sa amqp_login(), amqp_login_with_properties() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_tune_connection(amqp_connection_state_t state, int channel_max, int frame_max, int heartbeat); /** * Get the maximum number of channels the connection can handle * * The maximum number of channels is set when connection negotiation takes * place in amqp_login() or amqp_login_with_properties(). * * \param [in] state the connection object * \return the maximum number of channels. 0 if there is no limit * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_get_channel_max(amqp_connection_state_t state); /** * Destroys an amqp_connection_state_t object * * Destroys a amqp_connection_state_t object that was created with * amqp_new_connection(). If the connection with the broker is open, it will be * implicitly closed with a reply code of 200 (success). Any memory that * would be freed with amqp_maybe_release_buffers() or * amqp_maybe_release_buffers_on_channel() will be freed, and use of that * memory will caused undefined behavior. * * \param [in] state the connection object * \return AMQP_STATUS_OK on success. amqp_status_enum value failure * * \sa amqp_new_connection() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_destroy_connection(amqp_connection_state_t state); /** * Process incoming data * * \warning This is a low-level function intended for those who want to * have greater control over input and output over the socket from the * broker. Correctly using this function requires in-depth knowledge of AMQP * and rabbitmq-c. * * For a given buffer of data received from the broker, decode the first * frame in the buffer. If more than one frame is contained in the input buffer * the return value will be less than the received_data size, the caller should * adjust received_data buffer descriptor to point to the beginning of the * buffer + the return value. * * \param [in] state the connection object * \param [in] received_data a buffer of data received from the broker. The * function will return the number of bytes of the buffer it used. The * function copies these bytes to an internal buffer: this part of the buffer * may be reused after this function successfully completes. * \param [in,out] decoded_frame caller should pass in a pointer to an * amqp_frame_t struct. If there is enough data in received_data for a * complete frame, decoded_frame->frame_type will be set to something OTHER * than 0. decoded_frame may contain members pointing to memory owned by * the state object. This memory can be recycled with amqp_maybe_release_buffers() * or amqp_maybe_release_buffers_on_channel() * \return number of bytes consumed from received_data or 0 if a 0-length * buffer was passed. A negative return value indicates failure. Possible errors: * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely in * an indeterminate state making recovery unlikely. Client should note the error * and terminate the application * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection * should be shutdown immediately * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the * broker. This is likely a protocol error and the connection should be * shutdown immediately * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class * was received from the broker. This is likely a protocol error and the * connection should be shutdown immediately * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_handle_input(amqp_connection_state_t state, amqp_bytes_t received_data, amqp_frame_t *decoded_frame); /** * Check to see if connection memory can be released * * \deprecated This function is deprecated in favor of * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel() * * Checks the state of an amqp_connection_state_t object to see if * amqp_release_buffers() can be called successfully. * * \param [in] state the connection object * \returns TRUE if the buffers can be released FALSE otherwise * * \sa amqp_release_buffers() amqp_maybe_release_buffers() * amqp_maybe_release_buffers_on_channel() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_boolean_t AMQP_CALL amqp_release_buffers_ok(amqp_connection_state_t state); /** * Release amqp_connection_state_t owned memory * * \deprecated This function is deprecated in favor of * amqp_maybe_release_buffers() or amqp_maybe_release_buffers_on_channel() * * \warning caller should ensure amqp_release_buffers_ok() returns true before * calling this function. Failure to do so may result in abort() being called. * * Release memory owned by the amqp_connection_state_t for reuse by the * library. Use of any memory returned by the library before this function is * called will result in undefined behavior. * * \note internally rabbitmq-c tries to reuse memory when possible. As a result * its possible calling this function may not have a noticeable effect on * memory usage. * * \param [in] state the connection object * * \sa amqp_release_buffers_ok() amqp_maybe_release_buffers() * amqp_maybe_release_buffers_on_channel() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_release_buffers(amqp_connection_state_t state); /** * Release amqp_connection_state_t owned memory * * Release memory owned by the amqp_connection_state_t object related to any * channel, allowing reuse by the library. Use of any memory returned by the * library before this function is called with result in undefined behavior. * * \note internally rabbitmq-c tries to reuse memory when possible. As a result * its possible calling this function may not have a noticeable effect on * memory usage. * * \param [in] state the connection object * * \sa amqp_maybe_release_buffers_on_channel() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_maybe_release_buffers(amqp_connection_state_t state); /** * Release amqp_connection_state_t owned memory related to a channel * * Release memory owned by the amqp_connection_state_t object related to the * specified channel, allowing reuse by the library. Use of any memory returned * the library for a specific channel will result in undefined behavior. * * \note internally rabbitmq-c tries to reuse memory when possible. As a result * its possible calling this function may not have a noticeable effect on * memory usage. * * \param [in] state the connection object * \param [in] channel the channel specifier for which memory should be * released. Note that the library does not care about the state of the * channel when calling this function * * \sa amqp_maybe_release_buffers() * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_maybe_release_buffers_on_channel(amqp_connection_state_t state, amqp_channel_t channel); /** * Send a frame to the broker * * \param [in] state the connection object * \param [in] frame the frame to send to the broker * \return AMQP_STATUS_OK on success, an amqp_status_enum value on error. * Possible error codes: * - AMQP_STATUS_BAD_AMQP_DATA the serialized form of the method or * properties was too large to fit in a single AMQP frame, or the * method contains an invalid value. The frame was not sent. * - AMQP_STATUS_TABLE_TOO_BIG the serialized form of an amqp_table_t is * too large to fit in a single AMQP frame. Frame was not sent. * - AMQP_STATUS_UNKNOWN_METHOD an invalid method type was passed in * - AMQP_STATUS_UNKNOWN_CLASS an invalid properties type was passed in * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. The frame * was sent * - AMQP_STATUS_SOCKET_ERROR * - AMQP_STATUS_SSL_ERROR * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_send_frame(amqp_connection_state_t state, amqp_frame_t const *frame); /** * Compare two table entries * * Works just like strcmp(), comparing two the table keys, datatype, then values * * \param [in] entry1 the entry on the left * \param [in] entry2 the entry on the right * \return 0 if entries are equal, 0 < if left is greater, 0 > if right is greater * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_table_entry_cmp(void const *entry1, void const *entry2); /** * Open a socket to a remote host * * \deprecated This function is deprecated in favor of amqp_socket_open() * * Looks up the hostname, then attempts to open a socket to the host using * the specified portnumber. It also sets various options on the socket to * improve performance and correctness. * * \param [in] hostname this can be a hostname or IP address. * Both IPv4 and IPv6 are acceptable * \param [in] portnumber the port to connect on. RabbitMQ brokers * listen on port 5672, and 5671 for SSL * \return a positive value indicates success and is the sockfd. A negative * value (see amqp_status_enum)is returned on failure. Possible error codes: * - AMQP_STATUS_TCP_SOCKETLIB_INIT_ERROR Initialization of underlying socket * library failed. * - AMQP_STATUS_HOSTNAME_RESOLUTION_FAILED hostname lookup failed. * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. errno or WSAGetLastError() * may return more useful information. * * \note IPv6 support was added in v0.3 * * \sa amqp_socket_open() amqp_set_sockfd() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_open_socket(char const *hostname, int portnumber); /** * Send initial AMQP header to the broker * * \warning this is a low level function intended for those who want to * interact with the broker at a very low level. Use of this function without * understanding what it does will result in AMQP protocol errors. * * This function sends the AMQP protocol header to the broker. * * \param [in] state the connection object * \return AMQP_STATUS_OK on success, a negative value on failure. Possible * error codes: * - AMQP_STATUS_CONNECTION_CLOSED the connection to the broker was closed. * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. It is likely the * underlying socket has been closed. errno or WSAGetLastError() may provide * further information. * - AMQP_STATUS_SSL_ERROR a SSL error occurred. The connection to the broker * was closed. * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_send_header(amqp_connection_state_t state); /** * Checks to see if there are any incoming frames ready to be read * * Checks to see if there are any amqp_frame_t objects buffered by the * amqp_connection_state_t object. Having one or more frames buffered means * that amqp_simple_wait_frame() or amqp_simple_wait_frame_noblock() will * return a frame without potentially blocking on a read() call. * * \param [in] state the connection object * \return TRUE if there are frames enqueued, FALSE otherwise * * \sa amqp_simple_wait_frame() amqp_simple_wait_frame_noblock() * amqp_data_in_buffer() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_boolean_t AMQP_CALL amqp_frames_enqueued(amqp_connection_state_t state); /** * Read a single amqp_frame_t * * Waits for the next amqp_frame_t frame to be read from the broker. * This function has the potential to block for a long time in the case of * waiting for a basic.deliver method frame from the broker. * * The library may buffer frames. When an amqp_connection_state_t object * has frames buffered calling amqp_simple_wait_frame() will return an * amqp_frame_t without entering a blocking read(). You can test to see if * an amqp_connection_state_t object has frames buffered by calling the * amqp_frames_enqueued() function. * * The library has a socket read buffer. When there is data in an * amqp_connection_state_t read buffer, amqp_simple_wait_frame() may return an * amqp_frame_t without entering a blocking read(). You can test to see if an * amqp_connection_state_t object has data in its read buffer by calling the * amqp_data_in_buffer() function. * * \param [in] state the connection object * \param [out] decoded_frame the frame * \return AMQP_STATUS_OK on success, an amqp_status_enum value * is returned otherwise. Possible errors include: * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely in * an indeterminate state making recovery unlikely. Client should note the error * and terminate the application * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection * should be shutdown immediately * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the * broker. This is likely a protocol error and the connection should be * shutdown immediately * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class * was received from the broker. This is likely a protocol error and the * connection should be shutdown immediately * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat * from the broker. The connection has been closed. * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has * been closed * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has * been closed. * * \sa amqp_simple_wait_frame_noblock() amqp_frames_enqueued() * amqp_data_in_buffer() * * \note as of v0.4.0 this function will no longer return heartbeat frames * when enabled by specifying a non-zero heartbeat value in amqp_login(). * Heartbeating is handled internally by the library. * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_simple_wait_frame(amqp_connection_state_t state, amqp_frame_t *decoded_frame); /** * Read a single amqp_frame_t with a timeout. * * Waits for the next amqp_frame_t frame to be read from the broker, up to * a timespan specified by tv. The function will return AMQP_STATUS_TIMEOUT * if the timeout is reached. The tv value is not modified by the function. * * If a 0 timeval is specified, the function behaves as if its non-blocking: it * will test to see if a frame can be read from the broker, and return immediately. * * If NULL is passed in for tv, the function will behave like * amqp_simple_wait_frame() and block until a frame is received from the broker * * The library may buffer frames. When an amqp_connection_state_t object * has frames buffered calling amqp_simple_wait_frame_noblock() will return an * amqp_frame_t without entering a blocking read(). You can test to see if an * amqp_connection_state_t object has frames buffered by calling the * amqp_frames_enqueued() function. * * The library has a socket read buffer. When there is data in an * amqp_connection_state_t read buffer, amqp_simple_wait_frame_noblock() may return * an amqp_frame_t without entering a blocking read(). You can test to see if an * amqp_connection_state_t object has data in its read buffer by calling the * amqp_data_in_buffer() function. * * \note This function does not return heartbeat frames. When enabled, heartbeating * is handed internally internally by the library * * \param [in,out] state the connection object * \param [out] decoded_frame the frame * \param [in] tv the maximum time to wait for a frame to be read. Setting * tv->tv_sec = 0 and tv->tv_usec = 0 will do a non-blocking read. Specifying * NULL for tv will make the function block until a frame is read. * \return AMQP_STATUS_OK on success. An amqp_status_enum value is returned * otherwise. Possible errors include: * - AMQP_STATUS_TIMEOUT the timeout was reached while waiting for a frame * from the broker. * - AMQP_STATUS_INVALID_PARAMETER the tv parameter contains an invalid value. * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely in * an indeterminate state making recovery unlikely. Client should note the error * and terminate the application * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection * should be shutdown immediately * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the * broker. This is likely a protocol error and the connection should be * shutdown immediately * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class * was received from the broker. This is likely a protocol error and the * connection should be shutdown immediately * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat * from the broker. The connection has been closed. * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has * been closed * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has * been closed. * * \sa amqp_simple_wait_frame() amqp_frames_enqueued() amqp_data_in_buffer() * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_simple_wait_frame_noblock(amqp_connection_state_t state, amqp_frame_t *decoded_frame, struct timeval *tv); /** * Waits for a specific method from the broker * * \warning You probably don't want to use this function. If this function * doesn't receive exactly the frame requested it closes the whole connection. * * Waits for a single method on a channel from the broker. * If a frame is received that does not match expected_channel * or expected_method the program will abort * * \param [in] state the connection object * \param [in] expected_channel the channel that the method should be delivered on * \param [in] expected_method the method to wait for * \param [out] output the method * \returns AMQP_STATUS_OK on success. An amqp_status_enum value is returned * otherwise. Possible errors include: * - AMQP_STATUS_WRONG_METHOD a frame containing the wrong method, wrong frame * type or wrong channel was received. The connection is closed. * - AMQP_STATUS_NO_MEMORY failure in allocating memory. The library is likely in * an indeterminate state making recovery unlikely. Client should note the error * and terminate the application * - AMQP_STATUS_BAD_AMQP_DATA bad AMQP data was received. The connection * should be shutdown immediately * - AMQP_STATUS_UNKNOWN_METHOD: an unknown method was received from the * broker. This is likely a protocol error and the connection should be * shutdown immediately * - AMQP_STATUS_UNKNOWN_CLASS: a properties frame with an unknown class * was received from the broker. This is likely a protocol error and the * connection should be shutdown immediately * - AMQP_STATUS_HEARTBEAT_TIMEOUT timed out while waiting for heartbeat * from the broker. The connection has been closed. * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. * - AMQP_STATUS_SOCKET_ERROR a socket error occurred. The connection has * been closed * - AMQP_STATUS_SSL_ERROR a SSL socket error occurred. The connection has * been closed. * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_simple_wait_method(amqp_connection_state_t state, amqp_channel_t expected_channel, amqp_method_number_t expected_method, amqp_method_t *output); /** * Sends a method to the broker * * This is a thin wrapper around amqp_send_frame(), providing a way to send * a method to the broker on a specified channel. * * \param [in] state the connection object * \param [in] channel the channel object * \param [in] id the method number * \param [in] decoded the method object * \returns AMQP_STATUS_OK on success, an amqp_status_enum value otherwise. * Possible errors include: * - AMQP_STATUS_BAD_AMQP_DATA the serialized form of the method or * properties was too large to fit in a single AMQP frame, or the * method contains an invalid value. The frame was not sent. * - AMQP_STATUS_TABLE_TOO_BIG the serialized form of an amqp_table_t is * too large to fit in a single AMQP frame. Frame was not sent. * - AMQP_STATUS_UNKNOWN_METHOD an invalid method type was passed in * - AMQP_STATUS_UNKNOWN_CLASS an invalid properties type was passed in * - AMQP_STATUS_TIMER_FAILURE system timer indicated failure. The frame * was sent * - AMQP_STATUS_SOCKET_ERROR * - AMQP_STATUS_SSL_ERROR * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_send_method(amqp_connection_state_t state, amqp_channel_t channel, amqp_method_number_t id, void *decoded); /** * Sends a method to the broker and waits for a method response * * \param [in] state the connection object * \param [in] channel the channel object * \param [in] request_id the method number of the request * \param [in] expected_reply_ids a 0 terminated array of expected response * method numbers * \param [in] decoded_request_method the method to be sent to the broker * \return a amqp_rpc_reply_t: * - r.reply_type == AMQP_RESPONSE_NORMAL. RPC completed successfully * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an * exception: * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details * of the exception. The client should amqp_send_method() a * amqp_channel_close_ok_t. The channel must be re-opened before it * can be used again. Any resources associated with the channel * (auto-delete exchanges, auto-delete queues, consumers) are invalid * and must be recreated before attempting to use them again. * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception * occurred, cast r.reply.decoded to amqp_connection_close_t* to see * details of the exception. The client amqp_send_method() a * amqp_connection_close_ok_t and disconnect from the broker. * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. An exception occurred * within the library. Examine r.library_error and compare it against * amqp_status_enum values to determine the error. * * \sa amqp_simple_rpc_decoded() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_simple_rpc(amqp_connection_state_t state, amqp_channel_t channel, amqp_method_number_t request_id, amqp_method_number_t *expected_reply_ids, void *decoded_request_method); /** * Sends a method to the broker and waits for a method response * * \param [in] state the connection object * \param [in] channel the channel object * \param [in] request_id the method number of the request * \param [in] reply_id the method number expected in response * \param [in] decoded_request_method the request method * \return a pointer to the method returned from the broker, or NULL on error. * On error amqp_get_rpc_reply() will return an amqp_rpc_reply_t with * details on the error that occurred. * * \since v0.1 */ AMQP_PUBLIC_FUNCTION void * AMQP_CALL amqp_simple_rpc_decoded(amqp_connection_state_t state, amqp_channel_t channel, amqp_method_number_t request_id, amqp_method_number_t reply_id, void *decoded_request_method); /** * Get the last global amqp_rpc_reply * * The API methods corresponding to most synchronous AMQP methods * return a pointer to the decoded method result. Upon error, they * return NULL, and we need some way of discovering what, if anything, * went wrong. amqp_get_rpc_reply() returns the most recent * amqp_rpc_reply_t instance corresponding to such an API operation * for the given connection. * * Only use it for operations that do not themselves return * amqp_rpc_reply_t; operations that do return amqp_rpc_reply_t * generally do NOT update this per-connection-global amqp_rpc_reply_t * instance. * * \param [in] state the connection object * \return the most recent amqp_rpc_reply_t: * - r.reply_type == AMQP_RESPONSE_NORMAL. RPC completed successfully * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an * exception: * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details * of the exception. The client should amqp_send_method() a * amqp_channel_close_ok_t. The channel must be re-opened before it * can be used again. Any resources associated with the channel * (auto-delete exchanges, auto-delete queues, consumers) are invalid * and must be recreated before attempting to use them again. * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception * occurred, cast r.reply.decoded to amqp_connection_close_t* to see * details of the exception. The client amqp_send_method() a * amqp_connection_close_ok_t and disconnect from the broker. * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. An exception occurred * within the library. Examine r.library_error and compare it against * amqp_status_enum values to determine the error. * * \sa amqp_simple_rpc_decoded() * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_get_rpc_reply(amqp_connection_state_t state); /** * Login to the broker * * After using amqp_open_socket and amqp_set_sockfd, call * amqp_login to complete connecting to the broker * * \param [in] state the connection object * \param [in] vhost the virtual host to connect to on the broker. The default * on most brokers is "/" * \param [in] channel_max the limit for number of channels for the connection. * 0 means no limit, and is a good default (AMQP_DEFAULT_MAX_CHANNELS) * Note that the maximum number of channels the protocol supports * is 65535 (2^16, with the 0-channel reserved) * \param [in] frame_max the maximum size of an AMQP frame on the wire to * request of the broker for this connection. 4096 is the minimum * size, 2^31-1 is the maximum, a good default is 131072 (128KB), or * AMQP_DEFAULT_FRAME_SIZE * \param [in] heartbeat the number of seconds between heartbeat frames to * request of the broker. A value of 0 disables heartbeats. * Note rabbitmq-c only has partial support for heartbeats, as of * v0.4.0 they are only serviced during amqp_basic_publish() and * amqp_simple_wait_frame()/amqp_simple_wait_frame_noblock() * \param [in] sasl_method the SASL method to authenticate with the broker. * followed by the authentication information. * For AMQP_SASL_METHOD_PLAIN, the AMQP_SASL_METHOD_PLAIN * should be followed by two arguments in this order: * const char* username, and const char* password. * \return amqp_rpc_reply_t indicating success or failure. * - r.reply_type == AMQP_RESPONSE_NORMAL. Login completed successfully * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. In most cases errors * from the broker when logging in will be represented by the broker closing * the socket. In this case r.library_error will be set to * AMQP_STATUS_CONNECTION_CLOSED. This error can represent a number of * error conditions including: invalid vhost, authentication failure. * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an * exception: * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details * of the exception. The client should amqp_send_method() a * amqp_channel_close_ok_t. The channel must be re-opened before it * can be used again. Any resources associated with the channel * (auto-delete exchanges, auto-delete queues, consumers) are invalid * and must be recreated before attempting to use them again. * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception * occurred, cast r.reply.decoded to amqp_connection_close_t* to see * details of the exception. The client amqp_send_method() a * amqp_connection_close_ok_t and disconnect from the broker. * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_login(amqp_connection_state_t state, char const *vhost, int channel_max, int frame_max, int heartbeat, amqp_sasl_method_enum sasl_method, ...); /** * Login to the broker passing a properties table * * This function is similar to amqp_login() and differs in that it provides a * way to pass client properties to the broker. This is commonly used to * negotiate newer protocol features as they are supported by the broker. * * \param [in] state the connection object * \param [in] vhost the virtual host to connect to on the broker. The default * on most brokers is "/" * \param [in] channel_max the limit for the number of channels for the connection. * 0 means no limit, and is a good default (AMQP_DEFAULT_MAX_CHANNELS) * Note that the maximum number of channels the protocol supports * is 65535 (2^16, with the 0-channel reserved) * \param [in] frame_max the maximum size of an AMQP frame ont he wire to * request of the broker for this connection. 4096 is the minimum * size, 2^31-1 is the maximum, a good default is 131072 (128KB), or * AMQP_DEFAULT_FRAME_SIZE * \param [in] heartbeat the number of seconds between heartbeat frame to * request of the broker. A value of 0 disables heartbeats. * Note rabbitmq-c only has partial support for hearts, as of * v0.4.0 heartbeats are only serviced during amqp_basic_publish(), * and amqp_simple_wait_frame()/amqp_simple_wait_frame_noblock() * \param [in] properties a table of properties to send the broker. * \param [in] sasl_method the SASL method to authenticate with the broker * followed by the authentication information. * For AMQP_SASL_METHOD_PLAN, the AMQP_SASL_METHOD_PLAIN parameter * should be followed by two arguments in this order: * const char* username, and const char* password. * \return amqp_rpc_reply_t indicating success or failure. * - r.reply_type == AMQP_RESPONSE_NORMAL. Login completed successfully * - r.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION. In most cases errors * from the broker when logging in will be represented by the broker closing * the socket. In this case r.library_error will be set to * AMQP_STATUS_CONNECTION_CLOSED. This error can represent a number of * error conditions including: invalid vhost, authentication failure. * - r.reply_type == AMQP_RESPONSE_SERVER_EXCEPTION. The broker returned an * exception: * - If r.reply.id == AMQP_CHANNEL_CLOSE_METHOD a channel exception * occurred, cast r.reply.decoded to amqp_channel_close_t* to see details * of the exception. The client should amqp_send_method() a * amqp_channel_close_ok_t. The channel must be re-opened before it * can be used again. Any resources associated with the channel * (auto-delete exchanges, auto-delete queues, consumers) are invalid * and must be recreated before attempting to use them again. * - If r.reply.id == AMQP_CONNECTION_CLOSE_METHOD a connection exception * occurred, cast r.reply.decoded to amqp_connection_close_t* to see * details of the exception. The client amqp_send_method() a * amqp_connection_close_ok_t and disconnect from the broker. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_login_with_properties(amqp_connection_state_t state, char const *vhost, int channel_max, int frame_max, int heartbeat, const amqp_table_t *properties, amqp_sasl_method_enum sasl_method, ...); struct amqp_basic_properties_t_; /** * Publish a message to the broker * * Publish a message on an exchange with a routing key. * * Note that at the AMQ protocol level basic.publish is an async method: * this means error conditions that occur on the broker (such as publishing to * a non-existent exchange) will not be reflected in the return value of this * function. * * in the return value from this function. * \param [in] state the connection object * \param [in] channel the channel identifier * \param [in] exchange the exchange on the broker to publish to * \param [in] routing_key the routing key to use when publishing the message * \param [in] mandatory indicate to the broker that the message MUST be routed * to a queue. If the broker cannot do this it should respond with * a basic.reject method. * \param [in] immediate indicate to the broker that the message MUST be delivered * to a consumer immediately. If the broker cannot do this it should * response with a basic.reject method. * \param [in] properties the properties associated with the message * \param [in] body the message body * \return AMQP_STATUS_OK on success, amqp_status_enum value on failure. Note * that basic.publish is an async method, the return value from this * function only indicates that the message data was successfully * transmitted to the broker. It does not indicate failures that occur * on the broker, such as publishing to a non-existent exchange. * Possible error values: * - AMQP_STATUS_TIMER_FAILURE: system timer facility returned an error * the message was not sent. * - AMQP_STATUS_HEARTBEAT_TIMEOUT: connection timed out waiting for a * heartbeat from the broker. The message was not sent. * - AMQP_STATUS_NO_MEMORY: memory allocation failed. The message was * not sent. * - AMQP_STATUS_TABLE_TOO_BIG: a table in the properties was too large * to fit in a single frame. Message was not sent. * - AMQP_STATUS_CONNECTION_CLOSED: the connection was closed. * - AMQP_STATUS_SSL_ERROR: a SSL error occurred. * - AMQP_STATUS_TCP_ERROR: a TCP error occurred. errno or * WSAGetLastError() may provide more information * * Note: this function does heartbeat processing as of v0.4.0 * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_basic_publish(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_boolean_t mandatory, amqp_boolean_t immediate, struct amqp_basic_properties_t_ const *properties, amqp_bytes_t body); /** * Closes an channel * * \param [in] state the connection object * \param [in] channel the channel identifier * \param [in] code the reason for closing the channel, AMQP_REPLY_SUCCESS is a good default * \return amqp_rpc_reply_t indicating success or failure * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_channel_close(amqp_connection_state_t state, amqp_channel_t channel, int code); /** * Closes the entire connection * * Implicitly closes all channels and informs the broker the connection * is being closed, after receiving acknowldgement from the broker it closes * the socket. * * \param [in] state the connection object * \param [in] code the reason code for closing the connection. AMQP_REPLY_SUCCESS is a good default. * \return amqp_rpc_reply_t indicating the result * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_connection_close(amqp_connection_state_t state, int code); /** * Acknowledges a message * * Does a basic.ack on a received message * * \param [in] state the connection object * \param [in] channel the channel identifier * \param [in] delivery_tag the delivery take of the message to be ack'd * \param [in] multiple if true, ack all messages up to this delivery tag, if * false ack only this delivery tag * \return 0 on success, 0 > on failing to send the ack to the broker. * this will not indicate failure if something goes wrong on the broker * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_basic_ack(amqp_connection_state_t state, amqp_channel_t channel, uint64_t delivery_tag, amqp_boolean_t multiple); /** * Do a basic.get * * Synchonously polls the broker for a message in a queue, and * retrieves the message if a message is in the queue. * * \param [in] state the connection object * \param [in] channel the channel identifier to use * \param [in] queue the queue name to retrieve from * \param [in] no_ack if true the message is automatically ack'ed * if false amqp_basic_ack should be called once the message * retrieved has been processed * \return amqp_rpc_reply indicating success or failure * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_basic_get(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, amqp_boolean_t no_ack); /** * Do a basic.reject * * Actively reject a message that has been delivered * * \param [in] state the connection object * \param [in] channel the channel identifier * \param [in] delivery_tag the delivery tag of the message to reject * \param [in] requeue indicate to the broker whether it should requeue the * message or just discard it. * \return 0 on success, 0 > on failing to send the reject method to the broker. * This will not indicate failure if something goes wrong on the broker. * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_basic_reject(amqp_connection_state_t state, amqp_channel_t channel, uint64_t delivery_tag, amqp_boolean_t requeue); /** * Check to see if there is data left in the receive buffer * * Can be used to see if there is data still in the buffer, if so * calling amqp_simple_wait_frame will not immediately enter a * blocking read. * * \param [in] state the connection object * \return true if there is data in the recieve buffer, false otherwise * * \since v0.1 */ AMQP_PUBLIC_FUNCTION amqp_boolean_t AMQP_CALL amqp_data_in_buffer(amqp_connection_state_t state); /** * Get the error string for the given error code. * * \deprecated This function has been deprecated in favor of * \ref amqp_error_string2() which returns statically allocated * string which do not need to be freed by the caller. * * The returned string resides on the heap; the caller is responsible * for freeing it. * * \param [in] err return error code * \return the error string * * \since v0.1 */ AMQP_DEPRECATED( AMQP_PUBLIC_FUNCTION char * AMQP_CALL amqp_error_string(int err) ); /** * Get the error string for the given error code. * * Get an error string associated with an error code. The string is statically * allocated and does not need to be freed * * \param [in] err the error code * \return the error string * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION const char * AMQP_CALL amqp_error_string2(int err); /** * Deserialize an amqp_table_t from AMQP wireformat * * This is an internal function and is not typically used by * client applications * * \param [in] encoded the buffer containing the serialized data * \param [in] pool memory pool used to allocate the table entries from * \param [in] output the amqp_table_t structure to fill in. Any existing * entries will be erased * \param [in,out] offset The offset into the encoded buffer to start * reading the serialized table. It will be updated * by this function to end of the table * \return AMQP_STATUS_OK on success, an amqp_status_enum value on failure * Possible error codes: * - AMQP_STATUS_NO_MEMORY out of memory * - AMQP_STATUS_BAD_AMQP_DATA invalid wireformat * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_decode_table(amqp_bytes_t encoded, amqp_pool_t *pool, amqp_table_t *output, size_t *offset); /** * Serializes an amqp_table_t to the AMQP wireformat * * This is an internal function and is not typically used by * client applications * * \param [in] encoded the buffer where to serialize the table to * \param [in] input the amqp_table_t to serialize * \param [in,out] offset The offset into the encoded buffer to start * writing the serialized table. It will be updated * by this function to where writing left off * \return AMQP_STATUS_OK on success, an amqp_status_enum value on failure * Possible error codes: * - AMQP_STATUS_TABLE_TOO_BIG the serialized form is too large for the * buffer * - AMQP_STATUS_BAD_AMQP_DATA invalid table * * \since v0.1 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_encode_table(amqp_bytes_t encoded, amqp_table_t *input, size_t *offset); /** * Create a deep-copy of an amqp_table_t object * * Creates a deep-copy of an amqp_table_t object, using the provided pool * object to allocate the necessary memory. This memory can be freed later by * call recycle_amqp_pool(), or empty_amqp_pool() * * \param [in] original the table to copy * \param [in,out] clone the table to copy to * \param [in] pool the initialized memory pool to do allocations for the table * from * \return AMQP_STATUS_OK on success, amqp_status_enum value on failure. * Possible error values: * - AMQP_STATUS_NO_MEMORY - memory allocation failure. * - AMQP_STATUS_INVALID_PARAMETER - invalid table (e.g., no key name) * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_table_clone(amqp_table_t *original, amqp_table_t *clone, amqp_pool_t *pool); /** * A message object * * \since v0.4.0 */ typedef struct amqp_message_t_ { amqp_basic_properties_t properties; /**< message properties */ amqp_bytes_t body; /**< message body */ amqp_pool_t pool; /**< pool used to allocate properties */ } amqp_message_t; /** * Reads the next message on a channel * * Reads a complete message (header + body) on a specified channel. This * function is intended to be used with amqp_basic_get() or when an * AMQP_BASIC_DELIVERY_METHOD method is received. * * \param [in,out] state the connection object * \param [in] channel the channel on which to read the message from * \param [in,out] message a pointer to a amqp_message_t object. Caller should * call amqp_message_destroy() when it is done using the * fields in the message object. The caller is responsible for * allocating/destroying the amqp_message_t object itself. * \param [in] flags pass in 0. Currently unused. * \returns a amqp_rpc_reply_t object. ret.reply_type == AMQP_RESPONSE_NORMAL on success. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_read_message(amqp_connection_state_t state, amqp_channel_t channel, amqp_message_t *message, int flags); /** * Frees memory associated with a amqp_message_t allocated in amqp_read_message * * \param [in] message * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_destroy_message(amqp_message_t *message); /** * Envelope object * * \since v0.4.0 */ typedef struct amqp_envelope_t_ { amqp_channel_t channel; /**< channel message was delivered on */ amqp_bytes_t consumer_tag; /**< the consumer tag the message was delivered to */ uint64_t delivery_tag; /**< the messages delivery tag */ amqp_boolean_t redelivered; /**< flag indicating whether this message is being redelivered */ amqp_bytes_t exchange; /**< exchange this message was published to */ amqp_bytes_t routing_key; /**< the routing key this message was published with */ amqp_message_t message; /**< the message */ } amqp_envelope_t; /** * Wait for and consume a message * * Waits for a basic.deliver method on any channel, upon receipt of * basic.deliver it reads that message, and returns. If any other method is * received before basic.deliver, this function will return an amqp_rpc_reply_t * with ret.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION, and * ret.library_error == AMQP_STATUS_UNEXPECTED_FRAME. The caller should then * call amqp_simple_wait_frame() to read this frame and take appropriate action. * * This function should be used after starting a consumer with the * amqp_basic_consume() function * * \param [in,out] state the connection object * \param [in,out] envelope a pointer to a amqp_envelope_t object. Caller * should call amqp_envelope_destroy() when it is done using * the fields in the envelope object. The caller is responsible * for allocating/destroying the amqp_envelope_t object itself. * \param [in] timeout a timeout to wait for a message delivery. Passing in * NULL will result in blocking behavior. * \param [in] flags pass in 0. Currently unused. * \returns a amqp_rpc_reply_t object. ret.reply_type == AMQP_RESPONSE_NORMAL * on success. If ret.reply_type == AMQP_RESPONSE_LIBRARY_EXCEPTION, and * ret.library_error == AMQP_STATUS_UNEXPECTED_FRAME, a frame other * than AMQP_BASIC_DELIVER_METHOD was received, the caller should call * amqp_simple_wait_frame() to read this frame and take appropriate * action. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION amqp_rpc_reply_t AMQP_CALL amqp_consume_message(amqp_connection_state_t state, amqp_envelope_t *envelope, struct timeval *timeout, int flags); /** * Frees memory associated with a amqp_envelope_t allocated in amqp_consume_message() * * \param [in] envelope * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_destroy_envelope(amqp_envelope_t *envelope); /** * Parameters used to connect to the RabbitMQ broker * * \since v0.2 */ struct amqp_connection_info { char *user; /**< the username to authenticate with the broker, default on most broker is 'guest' */ char *password; /**< the password to authenticate with the broker, default on most brokers is 'guest' */ char *host; /**< the hostname of the broker */ char *vhost; /**< the virtual host on the broker to connect to, a good default is "/" */ int port; /**< the port that the broker is listening on, default on most brokers is 5672 */ amqp_boolean_t ssl; }; /** * Initialze an amqp_connection_info to default values * * The default values are: * - user: "guest" * - password: "guest" * - host: "localhost" * - vhost: "/" * - port: 5672 * * \param [out] parsed the connection info to set defaults on * * \since v0.2 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_default_connection_info(struct amqp_connection_info *parsed); /** * Parse a connection URL * * An amqp connection url takes the form: * * amqp://[$USERNAME[:$PASSWORD]\@]$HOST[:$PORT]/[$VHOST] * * Examples: * amqp://guest:guest\@localhost:5672// * amqp://guest:guest\@localhost/myvhost * * \note This function modifies url parameter. * * \param [in] url URI to parse, note that this parameter is modified by the * function. * \param [out] parsed the connection info gleaned from the URI. The char* * members will point to parts of the url input parameter. * Memory management will depend on how the url is allocated. * \returns AMQP_STATUS_OK on success, AMQP_STATUS_BAD_URL on failure * * \since v0.2 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_parse_url(char *url, struct amqp_connection_info *parsed); /* socket API */ /** * Open a socket connection. * * This function opens a socket connection returned from amqp_tcp_socket_new() * or amqp_ssl_socket_new(). This function should be called after setting * socket options and prior to assigning the socket to an AMQP connection with * amqp_set_socket(). * * \param [in,out] self A socket object. * \param [in] host Connect to this host. * \param [in] port Connect on this remote port. * * \return AMQP_STATUS_OK on success, an amqp_status_enum on failure * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_socket_open(amqp_socket_t *self, const char *host, int port); /** * Open a socket connection. * * This function opens a socket connection returned from amqp_tcp_socket_new() * or amqp_ssl_socket_new(). This function should be called after setting * socket options and prior to assigning the socket to an AMQP connection with * amqp_set_socket(). * * \param [in,out] self A socket object. * \param [in] host Connect to this host. * \param [in] port Connect on this remote port. * \param [in] timeout Max allowed time to spent on opening. If NULL - run in blocking mode * * \return AMQP_STATUS_OK on success, an amqp_status_enum on failure. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_socket_open_noblock(amqp_socket_t *self, const char *host, int port, struct timeval *timeout); /** * Get the socket descriptor in use by a socket object. * * Retrieve the underlying socket descriptor. This function can be used to * perform low-level socket operations that aren't supported by the socket * interface. Use with caution! * * \param [in,out] self A socket object. * * \return The underlying socket descriptor, or -1 if there is no socket descriptor * associated with * with * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_socket_get_sockfd(amqp_socket_t *self); /** * Get the socket object associated with a amqp_connection_state_t * * \param [in] state the connection object to get the socket from * \return a pointer to the socket object, or NULL if one has not been assigned * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION amqp_socket_t * amqp_get_socket(amqp_connection_state_t state); AMQP_END_DECLS #endif /* AMQP_H */ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/amqp_framing.h0000664000175000017500000005720500000000000022663 0ustar00zuulzuul00000000000000/* Generated code. Do not edit. Edit and re-run codegen.py instead. * * ***** BEGIN LICENSE BLOCK ***** * Version: MIT * * Portions created by Alan Antonuk are Copyright (c) 2012-2013 * Alan Antonuk. All Rights Reserved. * * Portions created by VMware are Copyright (c) 2007-2012 VMware, Inc. * All Rights Reserved. * * Portions created by Tony Garnock-Jones are Copyright (c) 2009-2010 * VMware, Inc. and Tony Garnock-Jones. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation * files (the "Software"), to deal in the Software without * restriction, including without limitation the rights to use, copy, * modify, merge, publish, distribute, sublicense, and/or sell copies * of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be * included in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * ***** END LICENSE BLOCK ***** */ #ifndef AMQP_FRAMING_H #define AMQP_FRAMING_H #include AMQP_BEGIN_DECLS #define AMQP_PROTOCOL_VERSION_MAJOR 0 #define AMQP_PROTOCOL_VERSION_MINOR 9 #define AMQP_PROTOCOL_VERSION_REVISION 1 #define AMQP_PROTOCOL_PORT 5672 #define AMQP_FRAME_METHOD 1 #define AMQP_FRAME_HEADER 2 #define AMQP_FRAME_BODY 3 #define AMQP_FRAME_HEARTBEAT 8 #define AMQP_FRAME_MIN_SIZE 4096 #define AMQP_FRAME_END 206 #define AMQP_REPLY_SUCCESS 200 #define AMQP_CONTENT_TOO_LARGE 311 #define AMQP_NO_ROUTE 312 #define AMQP_NO_CONSUMERS 313 #define AMQP_ACCESS_REFUSED 403 #define AMQP_NOT_FOUND 404 #define AMQP_RESOURCE_LOCKED 405 #define AMQP_PRECONDITION_FAILED 406 #define AMQP_CONNECTION_FORCED 320 #define AMQP_INVALID_PATH 402 #define AMQP_FRAME_ERROR 501 #define AMQP_SYNTAX_ERROR 502 #define AMQP_COMMAND_INVALID 503 #define AMQP_CHANNEL_ERROR 504 #define AMQP_UNEXPECTED_FRAME 505 #define AMQP_RESOURCE_ERROR 506 #define AMQP_NOT_ALLOWED 530 #define AMQP_NOT_IMPLEMENTED 540 #define AMQP_INTERNAL_ERROR 541 /* Function prototypes. */ AMQP_PUBLIC_FUNCTION char const * AMQP_CALL amqp_constant_name(int constantNumber); AMQP_PUBLIC_FUNCTION amqp_boolean_t AMQP_CALL amqp_constant_is_hard_error(int constantNumber); AMQP_PUBLIC_FUNCTION char const * AMQP_CALL amqp_method_name(amqp_method_number_t methodNumber); AMQP_PUBLIC_FUNCTION amqp_boolean_t AMQP_CALL amqp_method_has_content(amqp_method_number_t methodNumber); AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_decode_method(amqp_method_number_t methodNumber, amqp_pool_t *pool, amqp_bytes_t encoded, void **decoded); AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_decode_properties(uint16_t class_id, amqp_pool_t *pool, amqp_bytes_t encoded, void **decoded); AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_encode_method(amqp_method_number_t methodNumber, void *decoded, amqp_bytes_t encoded); AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_encode_properties(uint16_t class_id, void *decoded, amqp_bytes_t encoded); /* Method field records. */ #define AMQP_CONNECTION_START_METHOD ((amqp_method_number_t) 0x000A000A) /* 10, 10; 655370 */ typedef struct amqp_connection_start_t_ { uint8_t version_major; uint8_t version_minor; amqp_table_t server_properties; amqp_bytes_t mechanisms; amqp_bytes_t locales; } amqp_connection_start_t; #define AMQP_CONNECTION_START_OK_METHOD ((amqp_method_number_t) 0x000A000B) /* 10, 11; 655371 */ typedef struct amqp_connection_start_ok_t_ { amqp_table_t client_properties; amqp_bytes_t mechanism; amqp_bytes_t response; amqp_bytes_t locale; } amqp_connection_start_ok_t; #define AMQP_CONNECTION_SECURE_METHOD ((amqp_method_number_t) 0x000A0014) /* 10, 20; 655380 */ typedef struct amqp_connection_secure_t_ { amqp_bytes_t challenge; } amqp_connection_secure_t; #define AMQP_CONNECTION_SECURE_OK_METHOD ((amqp_method_number_t) 0x000A0015) /* 10, 21; 655381 */ typedef struct amqp_connection_secure_ok_t_ { amqp_bytes_t response; } amqp_connection_secure_ok_t; #define AMQP_CONNECTION_TUNE_METHOD ((amqp_method_number_t) 0x000A001E) /* 10, 30; 655390 */ typedef struct amqp_connection_tune_t_ { uint16_t channel_max; uint32_t frame_max; uint16_t heartbeat; } amqp_connection_tune_t; #define AMQP_CONNECTION_TUNE_OK_METHOD ((amqp_method_number_t) 0x000A001F) /* 10, 31; 655391 */ typedef struct amqp_connection_tune_ok_t_ { uint16_t channel_max; uint32_t frame_max; uint16_t heartbeat; } amqp_connection_tune_ok_t; #define AMQP_CONNECTION_OPEN_METHOD ((amqp_method_number_t) 0x000A0028) /* 10, 40; 655400 */ typedef struct amqp_connection_open_t_ { amqp_bytes_t virtual_host; amqp_bytes_t capabilities; amqp_boolean_t insist; } amqp_connection_open_t; #define AMQP_CONNECTION_OPEN_OK_METHOD ((amqp_method_number_t) 0x000A0029) /* 10, 41; 655401 */ typedef struct amqp_connection_open_ok_t_ { amqp_bytes_t known_hosts; } amqp_connection_open_ok_t; #define AMQP_CONNECTION_CLOSE_METHOD ((amqp_method_number_t) 0x000A0032) /* 10, 50; 655410 */ typedef struct amqp_connection_close_t_ { uint16_t reply_code; amqp_bytes_t reply_text; uint16_t class_id; uint16_t method_id; } amqp_connection_close_t; #define AMQP_CONNECTION_CLOSE_OK_METHOD ((amqp_method_number_t) 0x000A0033) /* 10, 51; 655411 */ typedef struct amqp_connection_close_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_connection_close_ok_t; #define AMQP_CHANNEL_OPEN_METHOD ((amqp_method_number_t) 0x0014000A) /* 20, 10; 1310730 */ typedef struct amqp_channel_open_t_ { amqp_bytes_t out_of_band; } amqp_channel_open_t; #define AMQP_CHANNEL_OPEN_OK_METHOD ((amqp_method_number_t) 0x0014000B) /* 20, 11; 1310731 */ typedef struct amqp_channel_open_ok_t_ { amqp_bytes_t channel_id; } amqp_channel_open_ok_t; #define AMQP_CHANNEL_FLOW_METHOD ((amqp_method_number_t) 0x00140014) /* 20, 20; 1310740 */ typedef struct amqp_channel_flow_t_ { amqp_boolean_t active; } amqp_channel_flow_t; #define AMQP_CHANNEL_FLOW_OK_METHOD ((amqp_method_number_t) 0x00140015) /* 20, 21; 1310741 */ typedef struct amqp_channel_flow_ok_t_ { amqp_boolean_t active; } amqp_channel_flow_ok_t; #define AMQP_CHANNEL_CLOSE_METHOD ((amqp_method_number_t) 0x00140028) /* 20, 40; 1310760 */ typedef struct amqp_channel_close_t_ { uint16_t reply_code; amqp_bytes_t reply_text; uint16_t class_id; uint16_t method_id; } amqp_channel_close_t; #define AMQP_CHANNEL_CLOSE_OK_METHOD ((amqp_method_number_t) 0x00140029) /* 20, 41; 1310761 */ typedef struct amqp_channel_close_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_channel_close_ok_t; #define AMQP_ACCESS_REQUEST_METHOD ((amqp_method_number_t) 0x001E000A) /* 30, 10; 1966090 */ typedef struct amqp_access_request_t_ { amqp_bytes_t realm; amqp_boolean_t exclusive; amqp_boolean_t passive; amqp_boolean_t active; amqp_boolean_t write; amqp_boolean_t read; } amqp_access_request_t; #define AMQP_ACCESS_REQUEST_OK_METHOD ((amqp_method_number_t) 0x001E000B) /* 30, 11; 1966091 */ typedef struct amqp_access_request_ok_t_ { uint16_t ticket; } amqp_access_request_ok_t; #define AMQP_EXCHANGE_DECLARE_METHOD ((amqp_method_number_t) 0x0028000A) /* 40, 10; 2621450 */ typedef struct amqp_exchange_declare_t_ { uint16_t ticket; amqp_bytes_t exchange; amqp_bytes_t type; amqp_boolean_t passive; amqp_boolean_t durable; amqp_boolean_t auto_delete; amqp_boolean_t internal; amqp_boolean_t nowait; amqp_table_t arguments; } amqp_exchange_declare_t; #define AMQP_EXCHANGE_DECLARE_OK_METHOD ((amqp_method_number_t) 0x0028000B) /* 40, 11; 2621451 */ typedef struct amqp_exchange_declare_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_exchange_declare_ok_t; #define AMQP_EXCHANGE_DELETE_METHOD ((amqp_method_number_t) 0x00280014) /* 40, 20; 2621460 */ typedef struct amqp_exchange_delete_t_ { uint16_t ticket; amqp_bytes_t exchange; amqp_boolean_t if_unused; amqp_boolean_t nowait; } amqp_exchange_delete_t; #define AMQP_EXCHANGE_DELETE_OK_METHOD ((amqp_method_number_t) 0x00280015) /* 40, 21; 2621461 */ typedef struct amqp_exchange_delete_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_exchange_delete_ok_t; #define AMQP_EXCHANGE_BIND_METHOD ((amqp_method_number_t) 0x0028001E) /* 40, 30; 2621470 */ typedef struct amqp_exchange_bind_t_ { uint16_t ticket; amqp_bytes_t destination; amqp_bytes_t source; amqp_bytes_t routing_key; amqp_boolean_t nowait; amqp_table_t arguments; } amqp_exchange_bind_t; #define AMQP_EXCHANGE_BIND_OK_METHOD ((amqp_method_number_t) 0x0028001F) /* 40, 31; 2621471 */ typedef struct amqp_exchange_bind_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_exchange_bind_ok_t; #define AMQP_EXCHANGE_UNBIND_METHOD ((amqp_method_number_t) 0x00280028) /* 40, 40; 2621480 */ typedef struct amqp_exchange_unbind_t_ { uint16_t ticket; amqp_bytes_t destination; amqp_bytes_t source; amqp_bytes_t routing_key; amqp_boolean_t nowait; amqp_table_t arguments; } amqp_exchange_unbind_t; #define AMQP_EXCHANGE_UNBIND_OK_METHOD ((amqp_method_number_t) 0x00280033) /* 40, 51; 2621491 */ typedef struct amqp_exchange_unbind_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_exchange_unbind_ok_t; #define AMQP_QUEUE_DECLARE_METHOD ((amqp_method_number_t) 0x0032000A) /* 50, 10; 3276810 */ typedef struct amqp_queue_declare_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_boolean_t passive; amqp_boolean_t durable; amqp_boolean_t exclusive; amqp_boolean_t auto_delete; amqp_boolean_t nowait; amqp_table_t arguments; } amqp_queue_declare_t; #define AMQP_QUEUE_DECLARE_OK_METHOD ((amqp_method_number_t) 0x0032000B) /* 50, 11; 3276811 */ typedef struct amqp_queue_declare_ok_t_ { amqp_bytes_t queue; uint32_t message_count; uint32_t consumer_count; } amqp_queue_declare_ok_t; #define AMQP_QUEUE_BIND_METHOD ((amqp_method_number_t) 0x00320014) /* 50, 20; 3276820 */ typedef struct amqp_queue_bind_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_bytes_t exchange; amqp_bytes_t routing_key; amqp_boolean_t nowait; amqp_table_t arguments; } amqp_queue_bind_t; #define AMQP_QUEUE_BIND_OK_METHOD ((amqp_method_number_t) 0x00320015) /* 50, 21; 3276821 */ typedef struct amqp_queue_bind_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_queue_bind_ok_t; #define AMQP_QUEUE_PURGE_METHOD ((amqp_method_number_t) 0x0032001E) /* 50, 30; 3276830 */ typedef struct amqp_queue_purge_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_boolean_t nowait; } amqp_queue_purge_t; #define AMQP_QUEUE_PURGE_OK_METHOD ((amqp_method_number_t) 0x0032001F) /* 50, 31; 3276831 */ typedef struct amqp_queue_purge_ok_t_ { uint32_t message_count; } amqp_queue_purge_ok_t; #define AMQP_QUEUE_DELETE_METHOD ((amqp_method_number_t) 0x00320028) /* 50, 40; 3276840 */ typedef struct amqp_queue_delete_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_boolean_t if_unused; amqp_boolean_t if_empty; amqp_boolean_t nowait; } amqp_queue_delete_t; #define AMQP_QUEUE_DELETE_OK_METHOD ((amqp_method_number_t) 0x00320029) /* 50, 41; 3276841 */ typedef struct amqp_queue_delete_ok_t_ { uint32_t message_count; } amqp_queue_delete_ok_t; #define AMQP_QUEUE_UNBIND_METHOD ((amqp_method_number_t) 0x00320032) /* 50, 50; 3276850 */ typedef struct amqp_queue_unbind_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_bytes_t exchange; amqp_bytes_t routing_key; amqp_table_t arguments; } amqp_queue_unbind_t; #define AMQP_QUEUE_UNBIND_OK_METHOD ((amqp_method_number_t) 0x00320033) /* 50, 51; 3276851 */ typedef struct amqp_queue_unbind_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_queue_unbind_ok_t; #define AMQP_BASIC_QOS_METHOD ((amqp_method_number_t) 0x003C000A) /* 60, 10; 3932170 */ typedef struct amqp_basic_qos_t_ { uint32_t prefetch_size; uint16_t prefetch_count; amqp_boolean_t global; } amqp_basic_qos_t; #define AMQP_BASIC_QOS_OK_METHOD ((amqp_method_number_t) 0x003C000B) /* 60, 11; 3932171 */ typedef struct amqp_basic_qos_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_basic_qos_ok_t; #define AMQP_BASIC_CONSUME_METHOD ((amqp_method_number_t) 0x003C0014) /* 60, 20; 3932180 */ typedef struct amqp_basic_consume_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_bytes_t consumer_tag; amqp_boolean_t no_local; amqp_boolean_t no_ack; amqp_boolean_t exclusive; amqp_boolean_t nowait; amqp_table_t arguments; } amqp_basic_consume_t; #define AMQP_BASIC_CONSUME_OK_METHOD ((amqp_method_number_t) 0x003C0015) /* 60, 21; 3932181 */ typedef struct amqp_basic_consume_ok_t_ { amqp_bytes_t consumer_tag; } amqp_basic_consume_ok_t; #define AMQP_BASIC_CANCEL_METHOD ((amqp_method_number_t) 0x003C001E) /* 60, 30; 3932190 */ typedef struct amqp_basic_cancel_t_ { amqp_bytes_t consumer_tag; amqp_boolean_t nowait; } amqp_basic_cancel_t; #define AMQP_BASIC_CANCEL_OK_METHOD ((amqp_method_number_t) 0x003C001F) /* 60, 31; 3932191 */ typedef struct amqp_basic_cancel_ok_t_ { amqp_bytes_t consumer_tag; } amqp_basic_cancel_ok_t; #define AMQP_BASIC_PUBLISH_METHOD ((amqp_method_number_t) 0x003C0028) /* 60, 40; 3932200 */ typedef struct amqp_basic_publish_t_ { uint16_t ticket; amqp_bytes_t exchange; amqp_bytes_t routing_key; amqp_boolean_t mandatory; amqp_boolean_t immediate; } amqp_basic_publish_t; #define AMQP_BASIC_RETURN_METHOD ((amqp_method_number_t) 0x003C0032) /* 60, 50; 3932210 */ typedef struct amqp_basic_return_t_ { uint16_t reply_code; amqp_bytes_t reply_text; amqp_bytes_t exchange; amqp_bytes_t routing_key; } amqp_basic_return_t; #define AMQP_BASIC_DELIVER_METHOD ((amqp_method_number_t) 0x003C003C) /* 60, 60; 3932220 */ typedef struct amqp_basic_deliver_t_ { amqp_bytes_t consumer_tag; uint64_t delivery_tag; amqp_boolean_t redelivered; amqp_bytes_t exchange; amqp_bytes_t routing_key; } amqp_basic_deliver_t; #define AMQP_BASIC_GET_METHOD ((amqp_method_number_t) 0x003C0046) /* 60, 70; 3932230 */ typedef struct amqp_basic_get_t_ { uint16_t ticket; amqp_bytes_t queue; amqp_boolean_t no_ack; } amqp_basic_get_t; #define AMQP_BASIC_GET_OK_METHOD ((amqp_method_number_t) 0x003C0047) /* 60, 71; 3932231 */ typedef struct amqp_basic_get_ok_t_ { uint64_t delivery_tag; amqp_boolean_t redelivered; amqp_bytes_t exchange; amqp_bytes_t routing_key; uint32_t message_count; } amqp_basic_get_ok_t; #define AMQP_BASIC_GET_EMPTY_METHOD ((amqp_method_number_t) 0x003C0048) /* 60, 72; 3932232 */ typedef struct amqp_basic_get_empty_t_ { amqp_bytes_t cluster_id; } amqp_basic_get_empty_t; #define AMQP_BASIC_ACK_METHOD ((amqp_method_number_t) 0x003C0050) /* 60, 80; 3932240 */ typedef struct amqp_basic_ack_t_ { uint64_t delivery_tag; amqp_boolean_t multiple; } amqp_basic_ack_t; #define AMQP_BASIC_REJECT_METHOD ((amqp_method_number_t) 0x003C005A) /* 60, 90; 3932250 */ typedef struct amqp_basic_reject_t_ { uint64_t delivery_tag; amqp_boolean_t requeue; } amqp_basic_reject_t; #define AMQP_BASIC_RECOVER_ASYNC_METHOD ((amqp_method_number_t) 0x003C0064) /* 60, 100; 3932260 */ typedef struct amqp_basic_recover_async_t_ { amqp_boolean_t requeue; } amqp_basic_recover_async_t; #define AMQP_BASIC_RECOVER_METHOD ((amqp_method_number_t) 0x003C006E) /* 60, 110; 3932270 */ typedef struct amqp_basic_recover_t_ { amqp_boolean_t requeue; } amqp_basic_recover_t; #define AMQP_BASIC_RECOVER_OK_METHOD ((amqp_method_number_t) 0x003C006F) /* 60, 111; 3932271 */ typedef struct amqp_basic_recover_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_basic_recover_ok_t; #define AMQP_BASIC_NACK_METHOD ((amqp_method_number_t) 0x003C0078) /* 60, 120; 3932280 */ typedef struct amqp_basic_nack_t_ { uint64_t delivery_tag; amqp_boolean_t multiple; amqp_boolean_t requeue; } amqp_basic_nack_t; #define AMQP_TX_SELECT_METHOD ((amqp_method_number_t) 0x005A000A) /* 90, 10; 5898250 */ typedef struct amqp_tx_select_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_select_t; #define AMQP_TX_SELECT_OK_METHOD ((amqp_method_number_t) 0x005A000B) /* 90, 11; 5898251 */ typedef struct amqp_tx_select_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_select_ok_t; #define AMQP_TX_COMMIT_METHOD ((amqp_method_number_t) 0x005A0014) /* 90, 20; 5898260 */ typedef struct amqp_tx_commit_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_commit_t; #define AMQP_TX_COMMIT_OK_METHOD ((amqp_method_number_t) 0x005A0015) /* 90, 21; 5898261 */ typedef struct amqp_tx_commit_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_commit_ok_t; #define AMQP_TX_ROLLBACK_METHOD ((amqp_method_number_t) 0x005A001E) /* 90, 30; 5898270 */ typedef struct amqp_tx_rollback_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_rollback_t; #define AMQP_TX_ROLLBACK_OK_METHOD ((amqp_method_number_t) 0x005A001F) /* 90, 31; 5898271 */ typedef struct amqp_tx_rollback_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_rollback_ok_t; #define AMQP_CONFIRM_SELECT_METHOD ((amqp_method_number_t) 0x0055000A) /* 85, 10; 5570570 */ typedef struct amqp_confirm_select_t_ { amqp_boolean_t nowait; } amqp_confirm_select_t; #define AMQP_CONFIRM_SELECT_OK_METHOD ((amqp_method_number_t) 0x0055000B) /* 85, 11; 5570571 */ typedef struct amqp_confirm_select_ok_t_ { char dummy; /* Dummy field to avoid empty struct */ } amqp_confirm_select_ok_t; /* Class property records. */ #define AMQP_CONNECTION_CLASS (0x000A) /* 10 */ typedef struct amqp_connection_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_connection_properties_t; #define AMQP_CHANNEL_CLASS (0x0014) /* 20 */ typedef struct amqp_channel_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_channel_properties_t; #define AMQP_ACCESS_CLASS (0x001E) /* 30 */ typedef struct amqp_access_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_access_properties_t; #define AMQP_EXCHANGE_CLASS (0x0028) /* 40 */ typedef struct amqp_exchange_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_exchange_properties_t; #define AMQP_QUEUE_CLASS (0x0032) /* 50 */ typedef struct amqp_queue_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_queue_properties_t; #define AMQP_BASIC_CLASS (0x003C) /* 60 */ #define AMQP_BASIC_CONTENT_TYPE_FLAG (1 << 15) #define AMQP_BASIC_CONTENT_ENCODING_FLAG (1 << 14) #define AMQP_BASIC_HEADERS_FLAG (1 << 13) #define AMQP_BASIC_DELIVERY_MODE_FLAG (1 << 12) #define AMQP_BASIC_PRIORITY_FLAG (1 << 11) #define AMQP_BASIC_CORRELATION_ID_FLAG (1 << 10) #define AMQP_BASIC_REPLY_TO_FLAG (1 << 9) #define AMQP_BASIC_EXPIRATION_FLAG (1 << 8) #define AMQP_BASIC_MESSAGE_ID_FLAG (1 << 7) #define AMQP_BASIC_TIMESTAMP_FLAG (1 << 6) #define AMQP_BASIC_TYPE_FLAG (1 << 5) #define AMQP_BASIC_USER_ID_FLAG (1 << 4) #define AMQP_BASIC_APP_ID_FLAG (1 << 3) #define AMQP_BASIC_CLUSTER_ID_FLAG (1 << 2) typedef struct amqp_basic_properties_t_ { amqp_flags_t _flags; amqp_bytes_t content_type; amqp_bytes_t content_encoding; amqp_table_t headers; uint8_t delivery_mode; uint8_t priority; amqp_bytes_t correlation_id; amqp_bytes_t reply_to; amqp_bytes_t expiration; amqp_bytes_t message_id; uint64_t timestamp; amqp_bytes_t type; amqp_bytes_t user_id; amqp_bytes_t app_id; amqp_bytes_t cluster_id; } amqp_basic_properties_t; #define AMQP_TX_CLASS (0x005A) /* 90 */ typedef struct amqp_tx_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_tx_properties_t; #define AMQP_CONFIRM_CLASS (0x0055) /* 85 */ typedef struct amqp_confirm_properties_t_ { amqp_flags_t _flags; char dummy; /* Dummy field to avoid empty struct */ } amqp_confirm_properties_t; /* API functions for methods */ AMQP_PUBLIC_FUNCTION amqp_channel_open_ok_t * AMQP_CALL amqp_channel_open(amqp_connection_state_t state, amqp_channel_t channel); AMQP_PUBLIC_FUNCTION amqp_channel_flow_ok_t * AMQP_CALL amqp_channel_flow(amqp_connection_state_t state, amqp_channel_t channel, amqp_boolean_t active); AMQP_PUBLIC_FUNCTION amqp_exchange_declare_ok_t * AMQP_CALL amqp_exchange_declare(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t exchange, amqp_bytes_t type, amqp_boolean_t passive, amqp_boolean_t durable, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_exchange_delete_ok_t * AMQP_CALL amqp_exchange_delete(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t exchange, amqp_boolean_t if_unused); AMQP_PUBLIC_FUNCTION amqp_exchange_bind_ok_t * AMQP_CALL amqp_exchange_bind(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t destination, amqp_bytes_t source, amqp_bytes_t routing_key, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_exchange_unbind_ok_t * AMQP_CALL amqp_exchange_unbind(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t destination, amqp_bytes_t source, amqp_bytes_t routing_key, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_queue_declare_ok_t * AMQP_CALL amqp_queue_declare(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, amqp_boolean_t passive, amqp_boolean_t durable, amqp_boolean_t exclusive, amqp_boolean_t auto_delete, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_queue_bind_ok_t * AMQP_CALL amqp_queue_bind(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_queue_purge_ok_t * AMQP_CALL amqp_queue_purge(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue); AMQP_PUBLIC_FUNCTION amqp_queue_delete_ok_t * AMQP_CALL amqp_queue_delete(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, amqp_boolean_t if_unused, amqp_boolean_t if_empty); AMQP_PUBLIC_FUNCTION amqp_queue_unbind_ok_t * AMQP_CALL amqp_queue_unbind(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, amqp_bytes_t exchange, amqp_bytes_t routing_key, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_basic_qos_ok_t * AMQP_CALL amqp_basic_qos(amqp_connection_state_t state, amqp_channel_t channel, uint32_t prefetch_size, uint16_t prefetch_count, amqp_boolean_t global); AMQP_PUBLIC_FUNCTION amqp_basic_consume_ok_t * AMQP_CALL amqp_basic_consume(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t queue, amqp_bytes_t consumer_tag, amqp_boolean_t no_local, amqp_boolean_t no_ack, amqp_boolean_t exclusive, amqp_table_t arguments); AMQP_PUBLIC_FUNCTION amqp_basic_cancel_ok_t * AMQP_CALL amqp_basic_cancel(amqp_connection_state_t state, amqp_channel_t channel, amqp_bytes_t consumer_tag); AMQP_PUBLIC_FUNCTION amqp_basic_recover_ok_t * AMQP_CALL amqp_basic_recover(amqp_connection_state_t state, amqp_channel_t channel, amqp_boolean_t requeue); AMQP_PUBLIC_FUNCTION amqp_tx_select_ok_t * AMQP_CALL amqp_tx_select(amqp_connection_state_t state, amqp_channel_t channel); AMQP_PUBLIC_FUNCTION amqp_tx_commit_ok_t * AMQP_CALL amqp_tx_commit(amqp_connection_state_t state, amqp_channel_t channel); AMQP_PUBLIC_FUNCTION amqp_tx_rollback_ok_t * AMQP_CALL amqp_tx_rollback(amqp_connection_state_t state, amqp_channel_t channel); AMQP_PUBLIC_FUNCTION amqp_confirm_select_ok_t * AMQP_CALL amqp_confirm_select(amqp_connection_state_t state, amqp_channel_t channel); AMQP_END_DECLS #endif /* AMQP_FRAMING_H */ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/amqp_ssl_socket.h0000664000175000017500000001170400000000000023403 0ustar00zuulzuul00000000000000/* vim:set ft=c ts=2 sw=2 sts=2 et cindent: */ /** \file */ /* * Copyright 2012-2013 Michael Steinert * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ #ifndef AMQP_SSL_H #define AMQP_SSL_H #include AMQP_BEGIN_DECLS /** * Create a new SSL/TLS socket object. * * The returned socket object is owned by the \ref amqp_connection_state_t object * and will be destroyed when the state object is destroyed or a new socket * object is created. * * If the socket object creation fails, the \ref amqp_connection_state_t object * will not be changed. * * The object returned by this function can be retrieved from the * amqp_connection_state_t object later using the amqp_get_socket() function. * * Calling this function may result in the underlying SSL library being initialized. * \sa amqp_set_initialize_ssl_library() * * \param [in,out] state The connection object that owns the SSL/TLS socket * \return A new socket object or NULL if an error occurred. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION amqp_socket_t * AMQP_CALL amqp_ssl_socket_new(amqp_connection_state_t state); /** * Set the CA certificate. * * \param [in,out] self An SSL/TLS socket object. * \param [in] cacert Path to the CA cert file in PEM format. * * \return \ref AMQP_STATUS_OK on success an enum * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_ssl_socket_set_cacert(amqp_socket_t *self, const char *cacert); /** * Set the client key. * * \param [in,out] self An SSL/TLS socket object. * \param [in] cert Path to the client certificate in PEM foramt. * \param [in] key Path to the client key in PEM format. * * \return Zero if successful, -1 otherwise. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_ssl_socket_set_key(amqp_socket_t *self, const char *cert, const char *key); /** * Set the client key from a buffer. * * \param [in,out] self An SSL/TLS socket object. * \param [in] cert Path to the client certificate in PEM foramt. * \param [in] key A buffer containing client key in PEM format. * \param [in] n The length of the buffer. * * \return Zero if successful, -1 otherwise. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION int AMQP_CALL amqp_ssl_socket_set_key_buffer(amqp_socket_t *self, const char *cert, const void *key, size_t n); /** * Enable or disable peer verification. * * If peer verification is enabled then the common name in the server * certificate must match the server name. Peer verification is enabled by * default. * * \param [in,out] self An SSL/TLS socket object. * \param [in] verify Enable or disable peer verification. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_ssl_socket_set_verify(amqp_socket_t *self, amqp_boolean_t verify); /** * Sets whether rabbitmq-c initializes the underlying SSL library. * * For SSL libraries that require a one-time initialization across * a whole program (e.g., OpenSSL) this sets whether or not rabbitmq-c * will initialize the SSL library when the first call to * amqp_open_socket() is made. You should call this function with * do_init = 0 if the underlying SSL library is initialized somewhere else * the program. * * Failing to initialize or double initialization of the SSL library will * result in undefined behavior * * By default rabbitmq-c will initialize the underlying SSL library * * NOTE: calling this function after the first socket has been opened with * amqp_open_socket() will not have any effect. * * \param [in] do_initalize If 0 rabbitmq-c will not initialize the SSL * library, otherwise rabbitmq-c will initialize the * SSL library * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_set_initialize_ssl_library(amqp_boolean_t do_initialize); AMQP_END_DECLS #endif /* AMQP_SSL_H */ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/amqp_tcp_socket.h0000664000175000017500000000404000000000000023363 0ustar00zuulzuul00000000000000/* vim:set ft=c ts=2 sw=2 sts=2 et cindent: */ /** \file */ /* * Copyright 2012-2013 Michael Steinert * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. */ /** * A TCP socket connection. */ #ifndef AMQP_TCP_SOCKET_H #define AMQP_TCP_SOCKET_H #include AMQP_BEGIN_DECLS /** * Create a new TCP socket. * * Call amqp_socket_close() to release socket resources. * * \return A new socket object or NULL if an error occurred. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION amqp_socket_t * AMQP_CALL amqp_tcp_socket_new(amqp_connection_state_t state); /** * Assign an open file descriptor to a socket object. * * This function must not be used in conjunction with amqp_socket_open(), i.e. * the socket connection should already be open(2) when this function is * called. * * \param [in,out] self A TCP socket object. * \param [in] sockfd An open socket descriptor. * * \since v0.4.0 */ AMQP_PUBLIC_FUNCTION void AMQP_CALL amqp_tcp_socket_set_sockfd(amqp_socket_t *base, int sockfd); AMQP_END_DECLS #endif /* AMQP_TCP_SOCKET_H */ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/lcfg_static.c0000664000175000017500000013305700000000000022477 0ustar00zuulzuul00000000000000/* This file is an autogenerated single-file version of liblcfg. * It is recommended that you update this file on a regular * basis from the original liblcfg distribution package. * * The most recent version of liblcfg is available at * */ #include #include #include #include #include #include #include #include #include #include #include #include "lcfg_static.h" /*** begin file include/lcfg/lcfg_string.h ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFG_STRING_H #define LCFG_STRING_H struct lcfg_string * lcfg_string_new(); struct lcfg_string * lcfg_string_new_copy(struct lcfg_string *); int lcfg_string_set(struct lcfg_string *, const char *); int lcfg_string_cat_char(struct lcfg_string *, char); int lcfg_string_cat_cstr(struct lcfg_string *, const char *); int lcfg_string_cat_uint(struct lcfg_string *, unsigned int); int lcfg_string_find(struct lcfg_string *, char); int lcfg_string_rfind(struct lcfg_string *, char); void lcfg_string_trunc(struct lcfg_string *, unsigned int); const char * lcfg_string_cstr(struct lcfg_string *); unsigned int lcfg_string_len(struct lcfg_string *); void lcfg_string_delete(struct lcfg_string *); #endif /*** end file include/lcfg/lcfg_string.h ***/ /*** begin file include/lcfg/lcfg_token.h ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFG_TOKEN_H #define LCFG_TOKEN_H enum lcfg_token_type { lcfg_null_token = 0, lcfg_identifier, lcfg_equals, lcfg_string, lcfg_sbracket_open, lcfg_sbracket_close, lcfg_comma, lcfg_brace_open, lcfg_brace_close }; extern const char *lcfg_token_map[]; struct lcfg_token { enum lcfg_token_type type; struct lcfg_string *string; short line; short col; }; #endif /*** end file include/lcfg/lcfg_token.h ***/ /*** begin file include/lcfg/lcfg_scanner.h ***/ #/* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFG_SCANNER_H #define LCFG_SCANNER_H struct lcfg_scanner; struct lcfg_token; struct lcfg_scanner * lcfg_scanner_new(struct lcfg *, int fd); enum lcfg_status lcfg_scanner_init(struct lcfg_scanner *); enum lcfg_status lcfg_scanner_next_token(struct lcfg_scanner *, struct lcfg_token *); int lcfg_scanner_has_next(struct lcfg_scanner *); void lcfg_scanner_delete(struct lcfg_scanner *); #endif /*** end file include/lcfg/lcfg_scanner.h ***/ /*** begin file include/lcfg/lcfg_parser.h ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFG_PARSER_H #define LCFG_PARSER_H struct lcfg_parser; struct lcfg_parser * lcfg_parser_new(struct lcfg *, const char *); enum lcfg_status lcfg_parser_run(struct lcfg_parser *); enum lcfg_status lcfg_parser_accept(struct lcfg_parser *, lcfg_visitor_function, void *); void lcfg_parser_delete(struct lcfg_parser *); enum lcfg_status lcfg_parser_get(struct lcfg_parser *, const char *, void **, size_t *); #endif /*** end file include/lcfg/lcfg_parser.h ***/ /*** begin file include/lcfgx/lcfgx_tree.h ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFGX_TREE_H #define LCFGX_TREE_H enum lcfgx_type { lcfgx_string, lcfgx_list, lcfgx_map, }; struct lcfgx_tree_node { enum lcfgx_type type; char *key; /* NULL for root node */ union { struct { void *data; size_t len; } string; struct lcfgx_tree_node *elements; /* in case of list or map type */ } value; struct lcfgx_tree_node *next; }; struct lcfgx_tree_node *lcfgx_tree_new(struct lcfg *); void lcfgx_tree_delete(struct lcfgx_tree_node *); void lcfgx_tree_dump(struct lcfgx_tree_node *node, int depth); enum lcfgx_path_access { LCFGX_PATH_NOT_FOUND, LCFGX_PATH_FOUND_WRONG_TYPE_BAD, LCFGX_PATH_FOUND_TYPE_OK, }; extern const char *lcfgx_path_access_strings[]; enum lcfgx_path_access lcfgx_get(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key, enum lcfgx_type type); enum lcfgx_path_access lcfgx_get_list(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key); enum lcfgx_path_access lcfgx_get_map(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key); enum lcfgx_path_access lcfgx_get_string(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key); #endif /*** end file include/lcfgx/lcfgx_tree.h ***/ /*** begin file src/lcfg_string.c ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ struct lcfg_string { char *str; unsigned int size; unsigned int capacity; }; int lcfg_string_set(struct lcfg_string *s, const char *cstr) { lcfg_string_trunc(s, 0); return lcfg_string_cat_cstr(s, cstr); } /* make sure new_size bytes fit into the string */ inline static void lcfg_string_grow(struct lcfg_string *s, unsigned int new_size) { /* always allocate one byte more than needed * to make _cstr() working in any case without realloc. */ while( (new_size + 1) > s->capacity ) { s->capacity *= 2; s->str = realloc(s->str, s->capacity); } } struct lcfg_string *lcfg_string_new() { struct lcfg_string *s = malloc(sizeof(struct lcfg_string)); assert(s); s->capacity = 8; s->size = 0; s->str = malloc(s->capacity); assert(s->str); return s; } struct lcfg_string *lcfg_string_new_copy(struct lcfg_string *s) { struct lcfg_string *s_new = malloc(sizeof(struct lcfg_string)); assert(s_new); s_new->capacity = s->capacity; s_new->size = s->size; s_new->str = malloc(s_new->capacity); memcpy(s_new->str, s->str, s_new->size); return s_new; } int lcfg_string_cat_uint(struct lcfg_string *s, unsigned int i) { unsigned int size_needed = 1; unsigned int ii = i; char c; while( ii >= 10 ) { size_needed++; ii /= 10; } lcfg_string_grow(s, s->size + size_needed); ii = size_needed - 1; do { c = '0' + i % 10; s->str[s->size + ii--] = c; i /= 10; } while( i != 0 ); s->size += size_needed; return s->size; } int lcfg_string_find(struct lcfg_string *s, char c) { int i; for( i = 0; i < s->size; i++ ) { if( s->str[i] == c ) { return i; } } return -1; } int lcfg_string_rfind(struct lcfg_string *s, char c) { int i; for( i = s->size - 1; i >= 0; i-- ) { if( s->str[i] == c ) { return i; } } return -1; } void lcfg_string_trunc(struct lcfg_string *s, unsigned int max_size) { if( max_size < s->size ) { s->size = max_size; } } int lcfg_string_cat_cstr(struct lcfg_string *s, const char *cstr) { size_t len = strlen(cstr); lcfg_string_grow(s, s->size + len); memcpy(s->str + s->size, cstr, len); s->size += len; return s->size; } int lcfg_string_cat_char(struct lcfg_string *s, char c) { lcfg_string_grow(s, s->size + 1); s->str[s->size++] = c; return s->size; } const char *lcfg_string_cstr(struct lcfg_string *s) { s->str[s->size] = '\0'; return s->str; } unsigned int lcfg_string_len(struct lcfg_string *s) { return s->size; } void lcfg_string_delete(struct lcfg_string *s) { free(s->str); free(s); } /*** end file src/lcfg_string.c ***/ /*** begin file src/lcfg_token.c ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ const char *lcfg_token_map[] = { "null_token", "T_IDENTIFIER", "`='", "T_STRING", "`['", "`]'", "`,'", "`{'", "`}'" }; /*** end file src/lcfg_token.c ***/ /*** begin file src/lcfg_scanner.c ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #define BUFFER_SIZE 0xff struct lcfg_scanner { struct lcfg *lcfg; int fd; char buffer[BUFFER_SIZE]; int offset; int size; int eof; short line; short col; struct lcfg_token prepared_token; int token_eof; }; static enum lcfg_status lcfg_scanner_buffer_fill(struct lcfg_scanner *s) { if( (s->size = read(s->fd, s->buffer, BUFFER_SIZE)) < 0 ) { lcfg_error_set(s->lcfg, "read(): %s", strerror(errno)); return lcfg_status_error; } else if( s->size == 0 ) { s->eof = !0; } else { s->offset = 0; } return lcfg_status_ok; } static inline int lcfg_scanner_char_eof(struct lcfg_scanner *s) { if( s->eof ) { return !0; } else { if( s->size == 0 || s->offset == BUFFER_SIZE ) { lcfg_scanner_buffer_fill(s); } if( s->size < BUFFER_SIZE && s->offset == s->size ) { s->eof = !0; } return s->eof; } } static enum lcfg_status lcfg_scanner_char_read(struct lcfg_scanner *s, char *c) { if( lcfg_scanner_char_eof(s) ) { lcfg_error_set(s->lcfg, "%s", "cannot read beyond eof"); return lcfg_status_error; } *c = s->buffer[s->offset++]; return lcfg_status_ok; } static enum lcfg_status lcfg_scanner_char_peek(struct lcfg_scanner *s, char *c) { if( lcfg_scanner_char_eof(s) ) { lcfg_error_set(s->lcfg, "%s", "cannot peek beyond eof"); return lcfg_status_error; } *c = s->buffer[s->offset]; return lcfg_status_ok; } /* the beautiful lowlevel fsm */ static enum lcfg_status lcfg_scanner_token_read(struct lcfg_scanner *s) { enum scanner_state { start = 0, comm_start, in_oneline, in_multiline, multiline_end, in_identifier, in_str, in_esc, esc_hex_exp_first, esc_hex_exp_second, invalid }; enum scanner_state state = start; char c = '\0'; char hex[3]; s->prepared_token.type = lcfg_null_token; while( !lcfg_scanner_char_eof(s) ) { int consume = !0; lcfg_scanner_char_peek(s, &c); switch( state ) { case start: switch( c ) { case ' ': case '\t': case '\r': case '\n': break; case '=': s->prepared_token.type = lcfg_equals; break; case '[': s->prepared_token.type = lcfg_sbracket_open; break; case ']': s->prepared_token.type = lcfg_sbracket_close; break; case '{': s->prepared_token.type = lcfg_brace_open; break; case '}': s->prepared_token.type = lcfg_brace_close; break; case ',': s->prepared_token.type = lcfg_comma; break; case '/': state = comm_start; break; case '"': state = in_str; lcfg_string_trunc(s->prepared_token.string, 0); break; default: if( isalpha(c) ) { lcfg_string_trunc(s->prepared_token.string, 0); lcfg_string_cat_char(s->prepared_token.string, c); state = in_identifier; } else { lcfg_error_set(s->lcfg, "parse error: invalid input character `%c' (0x%02x) near line %d, col %d", isprint(c) ? c : '.', c, s->line, s->col); state = invalid; } } break; case comm_start: if( c == '/' ) { state = in_oneline; } else if( c == '*' ) { state = in_multiline; } else { lcfg_error_set(s->lcfg, "parse error: invalid input character `%c' (0x%02x) near line %d, col %d", isprint(c) ? c : '.', c, s->line, s->col); state = invalid; } break; case in_oneline: if( c == '\n' ) { state = start; } break; case in_multiline: if( c == '*' ) { state = multiline_end; } break; case multiline_end: if( c == '/' ) { state = start; } else if( c != '*' ) { state = in_multiline; } break; case in_identifier: if( isalnum(c) || c == '-' || c == '_' ) { lcfg_string_cat_char(s->prepared_token.string, c); } else { s->prepared_token.type = lcfg_identifier; consume = 0; state = start; } break; case in_str: if( c == '"' ) { s->prepared_token.type = lcfg_string; state = start; } else if( c == '\\' ) { state = in_esc; } else { lcfg_string_cat_char(s->prepared_token.string, c); } break; case in_esc: state = in_str; switch( c ) { case '"': lcfg_string_cat_char(s->prepared_token.string, '"'); break; case 'n': lcfg_string_cat_char(s->prepared_token.string, '\n'); break; case 't': lcfg_string_cat_char(s->prepared_token.string, '\t'); break; case 'r': lcfg_string_cat_char(s->prepared_token.string, '\r'); break; case '0': lcfg_string_cat_char(s->prepared_token.string, '\0'); break; case '\\': lcfg_string_cat_char(s->prepared_token.string, '\\'); break; case 'x': state = esc_hex_exp_first; break; default: lcfg_error_set(s->lcfg, "invalid string escape sequence `%c' near line %d, col %d", c, s->line, s->col); state = invalid; } break; case esc_hex_exp_first: if( !isxdigit(c) ) { lcfg_error_set(s->lcfg, "invalid hex escape sequence `%c' on line %d column %d", c, s->line, s->col); state = invalid; } hex[0] = c; state = esc_hex_exp_second; break; case esc_hex_exp_second: if( !isxdigit(c) ) { lcfg_error_set(s->lcfg, "invalid hex escape sequence `%c' on line %d column %d", c, s->line, s->col); state = invalid; } hex[1] = c; hex[2] = '\0'; lcfg_string_cat_char(s->prepared_token.string, strtoul(hex, NULL, 16)); state = in_str; break; case invalid: break; } /*#include printf("read %c at line %d column %d, new state is %d\n", isprint(c) ? c : '.', s->line, s->col, state);*/ /* this is technically not optimal (token position identified by last char), but it will suffice for now */ s->prepared_token.line = s->line; s->prepared_token.col = s->col; if( consume ) { lcfg_scanner_char_read(s, &c); if( c == '\n' ) { s->line++; s->col = 1; } else { s->col++; } } if( s->prepared_token.type != lcfg_null_token || state == invalid ) { break; } } if( state != start ) { if( state != invalid ) { lcfg_error_set(s->lcfg, "parse error: premature end of file near line %d, col %d", s->line, s->col); } return lcfg_status_error; } return lcfg_status_ok; } enum lcfg_status lcfg_scanner_init(struct lcfg_scanner *s) { /* prepare the first token */ return lcfg_scanner_token_read(s); } int lcfg_scanner_has_next(struct lcfg_scanner *s) { return s->prepared_token.type != lcfg_null_token; } enum lcfg_status lcfg_scanner_next_token(struct lcfg_scanner *s, struct lcfg_token *t) { if( !lcfg_scanner_has_next(s) ) { lcfg_error_set(s->lcfg, "%s", "cannot access tokenstream beyond eof"); return lcfg_status_error; } memcpy(t, &s->prepared_token, sizeof(struct lcfg_token)); t->string = lcfg_string_new_copy(s->prepared_token.string); /* prepare the next token */ return lcfg_scanner_token_read(s); } struct lcfg_scanner *lcfg_scanner_new(struct lcfg *c, int fd) { struct lcfg_scanner *s = malloc(sizeof(struct lcfg_scanner)); assert(s); memset(s, 0, sizeof(struct lcfg_scanner)); s->lcfg = c; s->fd = fd; s->line = s->col = 1; s->prepared_token.string = lcfg_string_new(); return s; } void lcfg_scanner_delete(struct lcfg_scanner *s) { lcfg_string_delete(s->prepared_token.string); free(s); } /*** end file src/lcfg_scanner.c ***/ /*** begin file src/lcfg_parser.c ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef strdup char *strdup(const char *s) { char *sdup; size_t len = strlen(s) + 1; sdup = malloc(len); if( sdup != NULL ) { memcpy(sdup, s, len); } return sdup; } #endif struct lcfg_parser_value_pair { char *key; struct lcfg_string *value; }; struct lcfg_parser { struct lcfg *lcfg; char *filename; struct lcfg_scanner *scanner; struct lcfg_parser_value_pair *values; unsigned int value_length; unsigned int value_capacity; }; static int lcfg_parser_add_value(struct lcfg_parser *p, const char *key, struct lcfg_string *value) { if( p->value_length == p->value_capacity ) { p->value_capacity *= 2; p->values = realloc(p->values, sizeof(struct lcfg_parser_value_pair) * p->value_capacity); assert(p->values); } p->values[p->value_length].key = strdup(key); p->values[p->value_length].value = lcfg_string_new_copy(value); return ++p->value_length; } struct lcfg_parser *lcfg_parser_new(struct lcfg *c, const char *filename) { struct lcfg_parser *p = malloc(sizeof(struct lcfg_parser)); assert(p); memset(p, 0, sizeof(struct lcfg_parser)); p->filename = strdup(filename); p->lcfg = c; p->value_length = 0; p->value_capacity = 8; p->values = malloc(sizeof(struct lcfg_parser_value_pair) * p->value_capacity); assert(p->values); return p; } /* this is a basic push down automata */ static enum lcfg_status lcfg_parser_parse(struct lcfg_parser *p) { enum state { top_level = 0, exp_equals, exp_value, in_list, in_map, invalid }; /*const char *state_map[] = { "top_level", "exp_equals", "exp_value", "in_list", "in_map", "invalid" };*/ struct state_element { enum state s; int list_counter; }; /* start of ugly preproc stuff */ #define STATE_STACK_PUSH(t) \ if( ssi + 1 == state_stack_size ) \ { \ state_stack_size *= 2; \ state_stack = realloc(state_stack, state_stack_size * sizeof(struct state_element)); \ } \ state_stack[++ssi].s = t; \ state_stack[ssi].list_counter = 0 #define STATE_STACK_POP() ssi-- #define PATH_PUSH_STR(s) \ if( lcfg_string_len(current_path) != 0 ) \ { \ lcfg_string_cat_char(current_path, '.'); \ } \ lcfg_string_cat_cstr(current_path, s); #define PATH_PUSH_INT(i) \ if( lcfg_string_len(current_path) != 0 ) \ { \ lcfg_string_cat_char(current_path, '.'); \ } \ lcfg_string_cat_uint(current_path, i); #define PATH_POP() \ if( lcfg_string_rfind(current_path, '.') != -1 ) \ { \ lcfg_string_trunc(current_path, lcfg_string_rfind(current_path, '.')); \ } \ else \ { \ lcfg_string_trunc(current_path, 0); \ } /* end of ugly preproc stuff */ if( lcfg_scanner_init(p->scanner) != lcfg_status_ok ) { return lcfg_status_error; } int state_stack_size = 8; int ssi = 0; /* ssi = state stack index */ struct state_element *state_stack = malloc(sizeof(struct state_element) * state_stack_size); state_stack[ssi].s = top_level; state_stack[ssi].list_counter = 0; struct lcfg_token t; struct lcfg_string *current_path = lcfg_string_new(); while( lcfg_scanner_has_next(p->scanner) && state_stack[ssi].s != invalid ) { if( lcfg_scanner_next_token(p->scanner, &t) != lcfg_status_ok ) { free(state_stack); lcfg_string_delete(t.string); lcfg_string_delete(current_path); return lcfg_status_error; } switch( state_stack[ssi].s ) { case top_level: case in_map: if( t.type == lcfg_identifier ) { PATH_PUSH_STR(lcfg_string_cstr(t.string)); STATE_STACK_PUSH(exp_equals); } else if( state_stack[ssi].s == in_map && t.type == lcfg_brace_close ) { STATE_STACK_POP(); PATH_POP(); } else { lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected identifier%s", lcfg_token_map[t.type], t.line, t.col, state_stack[ssi].s == in_map ? " or `}'" : ""); state_stack[ssi].s = invalid; } break; case exp_equals: if( t.type == lcfg_equals ) state_stack[ssi].s = exp_value; else { lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected `='", lcfg_token_map[t.type], t.line, t.col); state_stack[ssi].s = invalid; } break; case exp_value: if( t.type == lcfg_string ) { lcfg_parser_add_value(p, lcfg_string_cstr(current_path), t.string); /*printf("adding string value for single statement\n");*/ STATE_STACK_POP(); PATH_POP(); } else if( t.type == lcfg_sbracket_open ) { state_stack[ssi].s = in_list; } else if( t.type == lcfg_brace_open ) { state_stack[ssi].s = in_map; } else { lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected string, `[' or `{'", lcfg_token_map[t.type], t.line, t.col); state_stack[ssi].s = invalid; } break; case in_list: if( t.type == lcfg_comma ); /* ignore comma */ else if( t.type == lcfg_string ) { PATH_PUSH_INT(state_stack[ssi].list_counter); lcfg_parser_add_value(p, lcfg_string_cstr(current_path), t.string); PATH_POP(); /*printf("adding string to list pos %d\n", state_stack[ssi].list_counter);*/ state_stack[ssi].list_counter++; } else if( t.type == lcfg_sbracket_open ) { PATH_PUSH_INT(state_stack[ssi].list_counter); /*printf("adding list to list pos %d\n", state_stack[ssi].list_counter);*/ state_stack[ssi].list_counter++; STATE_STACK_PUSH(in_list); } else if( t.type == lcfg_brace_open ) { PATH_PUSH_INT(state_stack[ssi].list_counter); /*printf("adding map to list pos %d\n", state_stack[ssi].list_counter);*/ state_stack[ssi].list_counter++; STATE_STACK_PUSH(in_map); } else if( t.type == lcfg_sbracket_close ) { PATH_POP(); STATE_STACK_POP(); } else { lcfg_error_set(p->lcfg, "invalid token (%s) near line %d column %d: expected string, `[', `{', `,' or `]'", lcfg_token_map[t.type], t.line, t.col); state_stack[ssi].s = invalid; } break; case invalid: /* unreachable */ assert(0); break; } lcfg_string_delete(t.string); /*printf(" *** pda: read %s, state is now %s\n", lcfg_token_map[t.type], state_map[state_stack[ssi].s]);*/ } lcfg_string_delete(current_path); if( state_stack[ssi].s == top_level && ssi == 0 ) { free(state_stack); return lcfg_status_ok; } else { free(state_stack); lcfg_error_set(p->lcfg, "%s", "unexpected end of file: unterminated list/map?"); return lcfg_status_error; } } enum lcfg_status lcfg_parser_run(struct lcfg_parser *p) { int fd = open(p->filename, 0); enum lcfg_status status; if( fd < 0 ) { lcfg_error_set(p->lcfg, "open(): %s", strerror(errno)); return lcfg_status_error; } p->scanner = lcfg_scanner_new(p->lcfg, fd); status = lcfg_parser_parse(p); close(fd); return status; } enum lcfg_status lcfg_parser_accept(struct lcfg_parser *p, lcfg_visitor_function fn, void *user_data) { int i; for( i = 0; i < p->value_length; i++ ) { if( fn(p->values[i].key, (void *)lcfg_string_cstr(p->values[i].value), lcfg_string_len(p->values[i].value), user_data) != lcfg_status_ok ) { lcfg_error_set(p->lcfg, "%s", "configuration value traversal aborted upon user request"); return lcfg_status_error; } } return lcfg_status_ok; } enum lcfg_status lcfg_parser_get(struct lcfg_parser *p, const char *key, void **data, size_t *len) { int i; for( i = 0; i < p->value_length; i++ ) { if( !strcmp(p->values[i].key, key) ) { *data = (void *)lcfg_string_cstr(p->values[i].value); *len = lcfg_string_len(p->values[i].value); return lcfg_status_ok; } } return lcfg_status_error; } void lcfg_parser_delete(struct lcfg_parser *p) { if( p->scanner != NULL ) { lcfg_scanner_delete(p->scanner); } int i; for( i = 0; i < p->value_length; i++ ) { free(p->values[i].key); lcfg_string_delete(p->values[i].value); } free(p->values); free(p->filename); free(p); } /*** end file src/lcfg_parser.c ***/ /*** begin file src/lcfg.c ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ struct lcfg { char error[0xff]; struct lcfg_parser *parser; }; struct lcfg *lcfg_new(const char *filename) { struct lcfg *c = malloc(sizeof(struct lcfg)); assert(c); memset(c, 0, sizeof(struct lcfg)); c->parser = lcfg_parser_new(c, filename); assert(c->parser); return c; } void lcfg_delete(struct lcfg *c) { lcfg_parser_delete(c->parser); free(c); } const char *lcfg_error_get(struct lcfg *c) { return c->error; } enum lcfg_status lcfg_parse(struct lcfg *c) { return lcfg_parser_run(c->parser); } enum lcfg_status lcfg_accept(struct lcfg *c, lcfg_visitor_function fn, void *user_data) { return lcfg_parser_accept(c->parser, fn, user_data); } enum lcfg_status lcfg_value_get(struct lcfg *c, const char *key, void **data, size_t *len) { return lcfg_parser_get(c->parser, key, data, len); } void lcfg_error_set(struct lcfg *c, const char *fmt, ...) { va_list ap; va_start(ap, fmt); vsnprintf(c->error, sizeof(c->error), fmt, ap); va_end(ap); } /*** end file src/lcfg.c ***/ /*** begin file src/lcfgx_tree.c ***/ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ static struct lcfgx_tree_node *lcfgx_tree_node_new(enum lcfgx_type type, const char *key) { struct lcfgx_tree_node *node = malloc(sizeof(struct lcfgx_tree_node)); node->type = type; if( key != NULL ) node->key = strdup(key); else node->key = NULL; node->next = NULL; return node; } void lcfgx_tree_dump(struct lcfgx_tree_node *node, int depth) { // printf("%s node %p node->key %s depth %i\n", __PRETTY_FUNCTION__, node, node->key, depth); void sp(int n) { int i; for( i = 0; i < n; i++ ) printf("%c", ' '); } sp(depth); if( node->key != NULL ) printf("%s", node->key); else printf("%s", "(none)"); struct lcfgx_tree_node *n; switch( node->type ) { case lcfgx_string: printf(" = \"%s\"\n", (char *)node->value.string.data); break; case lcfgx_list: case lcfgx_map: printf("%c", '\n'); n = node->value.elements; for( ; n != NULL; n = n->next ) lcfgx_tree_dump(n, depth + 2); break; } } static void lcfgx_tree_insert(int pathc, char **pathv, void *data, size_t len, struct lcfgx_tree_node *node) { struct lcfgx_tree_node *n; for( n = node->value.elements; n != NULL; n = n->next ) if( !strcmp(pathv[0], n->key) ) break; if( pathc == 1 ) { /* leaf node --> string value */ if( n == NULL ) { /* not found, insert */ n = lcfgx_tree_node_new(lcfgx_string, pathv[0]); n->value.string.len = len; n->value.string.data = malloc(len+1); memset(n->value.string.data, 0, len+1); memcpy(n->value.string.data, data, len); n->next = NULL; if ( node->value.elements != NULL ) { struct lcfgx_tree_node *end = node->value.elements; while (end->next != NULL) end = end->next; end->next = n; }else { node->value.elements = n; } } } else { /* inner node --> (map/list) */ if( n == NULL ) { /* not found, insert it */ n = lcfgx_tree_node_new(lcfgx_map, pathv[0]); n->value.elements = NULL; n->next = NULL; if ( node->value.elements != NULL ) { struct lcfgx_tree_node *end = node->value.elements; while (end->next != NULL) end = end->next; end->next = n; }else { node->value.elements = n; } } /* recurse into map/list */ lcfgx_tree_insert(pathc - 1, &pathv[1], data, len, n); } } enum lcfg_status lcfgx_tree_visitor(const char *key, void *data, size_t len, void *user_data) { struct lcfgx_tree_node *root = user_data; char path[strlen(key) + 1]; int path_components = 1; strncpy(path, key, strlen(key) + 1); while( *key != 0 ) if( *key++ == '.' ) path_components++; char *pathv[path_components]; char *token; char *saveptr = NULL; int pathc = 0; while( (token = strtok_r(pathc == 0 ? path : NULL, ".", &saveptr)) != NULL ) pathv[pathc++] = token; lcfgx_tree_insert(pathc, pathv, data, len, root); return lcfg_status_ok; } void lcfgx_correct_type(struct lcfgx_tree_node *node) { if( node->type == lcfgx_string ) return; struct lcfgx_tree_node *n = NULL; if( node->key == NULL ) /* root node */ n = node; if( node->type == lcfgx_map || node->type == lcfgx_list ) n = node->value.elements; if( n == NULL ) return; /* child key is integer, we have a list */ char *end; if( strtol(n->key, &end, 10) >= 0 && n->key != end ) node->type = lcfgx_list; struct lcfgx_tree_node *it; for( it = n; it != NULL; it = it->next ) lcfgx_correct_type(it); } struct lcfgx_tree_node *lcfgx_tree_new(struct lcfg *c) { struct lcfgx_tree_node *root = lcfgx_tree_node_new(lcfgx_map, NULL); root->value.elements = NULL; lcfg_accept(c, lcfgx_tree_visitor, root); lcfgx_correct_type(root); return root; } void lcfgx_tree_delete(struct lcfgx_tree_node *n) { if( n->type != lcfgx_string ) { struct lcfgx_tree_node *m, *next; for( m = n->value.elements; m != NULL; ) { next = m->next; lcfgx_tree_delete(m); m = next; } } else { free(n->value.string.data); } if( n->key != NULL ) free(n->key); free(n); } const char *lcfgx_path_access_strings[] = { "LCFGX_PATH_NOT_FOUND", "LCFGX_PATH_FOUND_WRONG_TYPE_BAD", "LCFGX_PATH_FOUND_TYPE_OK", }; struct lcfgx_tree_node *cfg_get_recursive(struct lcfgx_tree_node *node, int pathc, char **pathv) { struct lcfgx_tree_node *it;// = node; for( it = node->value.elements; it != NULL; it = it->next ) { if( strcmp(pathv[0], it->key) == 0 ) break; } if( it != NULL ) { if( pathc == 1 ) return it; else return cfg_get_recursive(it, pathc - 1, &pathv[1]); } else return NULL; } enum lcfgx_path_access lcfgx_get(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key, enum lcfgx_type type) { char path[strlen(key) + 1]; int path_components = 1; strncpy(path, key, strlen(key) + 1); while( *key != 0 ) if( *key++ == '.' ) path_components++; char *pathv[path_components]; char *token; char *saveptr = NULL; int pathc = 0; while( (token = strtok_r(pathc == 0 ? path : NULL, ".", &saveptr)) != NULL ) pathv[pathc++] = token; struct lcfgx_tree_node *node; if( pathc == 0 ) node = root; else node = cfg_get_recursive(root, pathc, pathv); if( node == NULL ) return LCFGX_PATH_NOT_FOUND; if( node->type != type ) return LCFGX_PATH_FOUND_WRONG_TYPE_BAD; *n = node; return LCFGX_PATH_FOUND_TYPE_OK; } enum lcfgx_path_access lcfgx_get_list(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key) { return lcfgx_get(root, n, key, lcfgx_list); } enum lcfgx_path_access lcfgx_get_map(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key) { return lcfgx_get(root, n, key, lcfgx_map); } enum lcfgx_path_access lcfgx_get_string(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key) { return lcfgx_get(root, n, key, lcfgx_string); } /*** end file src/lcfgx_tree.c ***/ ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/lcfg_static.h0000664000175000017500000001254400000000000022501 0ustar00zuulzuul00000000000000/* This file is an autogenerated single-file version of liblcfg. * It is recommended that you update this file on a regular * basis from the original liblcfg distribution package. * * The most recent version of liblcfg is available at * */ /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFG_H #define LCFG_H #include struct lcfg; enum lcfg_status { lcfg_status_ok, lcfg_status_error }; typedef enum lcfg_status (*lcfg_visitor_function)(const char *key, void *data, size_t size, void *user_data); /* open a new config file */ struct lcfg * lcfg_new(const char *filename); /* parse config into memory */ enum lcfg_status lcfg_parse(struct lcfg *); /* visit all configuration elements */ enum lcfg_status lcfg_accept(struct lcfg *, lcfg_visitor_function, void *); /* access a value by path */ enum lcfg_status lcfg_value_get(struct lcfg *, const char *, void **, size_t *); /* return the last error message */ const char * lcfg_error_get(struct lcfg *); /* set error */ void lcfg_error_set(struct lcfg *, const char *fmt, ...); /* destroy lcfg context */ void lcfg_delete(struct lcfg *); #endif /* Copyright (c) 2012, Paul Baecher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef LCFGX_TREE_H #define LCFGX_TREE_H enum lcfgx_type { lcfgx_string, lcfgx_list, lcfgx_map, }; struct lcfgx_tree_node { enum lcfgx_type type; char *key; /* NULL for root node */ union { struct { void *data; size_t len; } string; struct lcfgx_tree_node *elements; /* in case of list or map type */ } value; struct lcfgx_tree_node *next; }; struct lcfgx_tree_node *lcfgx_tree_new(struct lcfg *); void lcfgx_tree_delete(struct lcfgx_tree_node *); void lcfgx_tree_dump(struct lcfgx_tree_node *node, int depth); enum lcfgx_path_access { LCFGX_PATH_NOT_FOUND, LCFGX_PATH_FOUND_WRONG_TYPE_BAD, LCFGX_PATH_FOUND_TYPE_OK, }; extern const char *lcfgx_path_access_strings[]; enum lcfgx_path_access lcfgx_get(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key, enum lcfgx_type type); enum lcfgx_path_access lcfgx_get_list(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key); enum lcfgx_path_access lcfgx_get_map(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key); enum lcfgx_path_access lcfgx_get_string(struct lcfgx_tree_node *root, struct lcfgx_tree_node **n, const char *key); #endif ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/librabbitmq.a0000664000175000017500000031404400000000000022500 0ustar00zuulzuul00000000000000! / 1380622529 0 0 0 2548 ` k xxxxxxxxxxxx$$$$$$$$$$$$$$$$$$$$$$$$$$$#`#`#`#`SDSDdXdXv v }}}}amqp_constant_nameamqp_constant_is_hard_erroramqp_method_nameamqp_method_has_contentamqp_decode_methodamqp_decode_propertiesamqp_encode_methodamqp_encode_propertiesamqp_channel_openamqp_channel_flowamqp_exchange_declareamqp_exchange_deleteamqp_exchange_bindamqp_exchange_unbindamqp_queue_declareamqp_queue_bindamqp_queue_purgeamqp_queue_deleteamqp_queue_unbindamqp_basic_qosamqp_basic_consumeamqp_basic_cancelamqp_basic_recoveramqp_tx_selectamqp_tx_commitamqp_tx_rollbackamqp_confirm_selectamqp_error_string2amqp_error_stringamqp_abortamqp_basic_publishamqp_channel_closeamqp_connection_closeamqp_basic_ackamqp_basic_getamqp_basic_rejectamqp_empty_arrayamqp_empty_tableamqp_empty_bytesamqp_new_connectionamqp_get_sockfdamqp_set_sockfdamqp_set_socketamqp_get_socketamqp_tune_connectionamqp_get_channel_maxamqp_destroy_connectionamqp_handle_inputamqp_release_buffers_okamqp_release_buffersamqp_maybe_release_buffersamqp_maybe_release_buffers_on_channelamqp_send_frameamqp_versionamqp_version_numberinit_amqp_poolrecycle_amqp_poolempty_amqp_poolamqp_pool_allocamqp_pool_alloc_bytesamqp_cstring_bytesamqp_bytes_malloc_dupamqp_bytes_mallocamqp_bytes_freeamqp_get_or_create_channel_poolamqp_get_channel_poolamqp_os_socket_erroramqp_os_socket_closeamqp_socket_writevamqp_socket_sendamqp_socket_recvamqp_socket_openamqp_socket_open_noblockamqp_socket_closeamqp_socket_deleteamqp_socket_get_sockfdamqp_open_socketamqp_open_socket_noblockamqp_send_headeramqp_frames_enqueuedamqp_data_in_bufferamqp_try_recvamqp_queue_frameamqp_simple_wait_frame_on_channelamqp_simple_wait_frameamqp_simple_wait_frame_noblockamqp_simple_wait_methodamqp_send_methodamqp_simple_rpcamqp_simple_rpc_decodedamqp_get_rpc_replyamqp_loginamqp_login_with_propertiesamqp_decode_tableamqp_encode_tableamqp_table_entry_cmpamqp_table_cloneamqp_default_connection_infoamqp_parse_urlamqp_tcp_socket_newamqp_tcp_socket_set_sockfdamqp_get_monotonic_timestampamqp_timer_updateamqp_destroy_messageamqp_destroy_envelopeamqp_read_messageamqp_consume_message// 80 ` amqp_framing.c.o/ amqp_connection.c.o/ amqp_tcp_socket.c.o/ amqp_consumer.c.o/ /0 1380622528 1000 1000 100664 33912 ` ELF>xU@@ tS~YtDt1;ttfDt~y9ttɸ@ttu[fbf~NPu#Ð7/8trff.ufDuÁufffff.| f.t}1@t؁t1Dwff.2tsvyG<td UtQZt> Zt+ Zt UqD1fDfD(t(t  2t((t3(t(ufD<t(<l<U<D<+Ð(  r2 3 ) D (  )v@ g) P 7Dd<'!P<Z<H<@22a(2)22f.n UZGZ6Z%1fD(( (22 2<<F<2<m <_ <N325 '  o<x<n<ff.wHtfD1DH\$Hl$HLd$Ll$ILt$HH2HMH$HL$HD$vWG< UqZ Zty Ztq Uc(@(h 2 & ((3(t(vfDIE1<&22f(2)2t 2LHHL$HQH9HT$T ʉIE1wf.(   "f > @LHIHH<$Ht$LD$HLHT$HBH9HD$LHH9HINIFHBH9HD$TʉHH9HIN IF(HBH9HD$w|TH H9wnHIV0IF8Mu1`o<Dx<n<@LHQHL$HQH9HT$H\$ Hl$(Ld$0Ll$8Lt$@HHD ( h  )f.f t(*2 &3 Z) ufLHyHL$HQH9HT$+L H4H9HHHPIE1 @d<P<KZ<?H<2mD(<$&<<><-DT IE1pPLHIHD$HPH9HT$8TffAHPH9HT$D(H H9IFHAHIVH9HD$L HH9HINIF HBH9HD$LHH9HIN(IF0HBH9HD$DIN@AF8H<$Ht$LD$LcMu1X @LHIHL$HQH9HT$L ɉH4H9f LHHT$HJH9HL$LffHJH9HL$t*HH9{HHpHHHJH9HL$^TPIE1M LHiHT$HJH9HL$LffHJH9HL$t*HH9HHpHHHJH9HL$LffHHJH9HL$T*ffPIE1LHHL$HQH9HT$jHL HH H ʉH HHT$HJH9HL$7TPIE1&f($( (\ < <32,PLHI HD$HPH9HT$TffAHPH9HT$iD(H H9WIFHAHIVH9HD$:L HH9(HINIF HBH9HD$ DIN@ƒAV(AV,AV0AF8AV4KHLHI HD$HPH9HT$TffAHPH9HT$qD(H H9_IFHAHIVH9HD$BL HH90HINIF HBH9HD$TH H9HL$HIV(IF0IN8l LH HT$HJH9HL$LffHJH9HL$t*HH9HHpHHHJH9HL$nTHPIE1SLHo HL$HQH9HT$!HL HH H ʉH HHT$HJH9HL$THP IE1 LH HT$HJH9HL$LɉHJH9HL$L*ffHHJH9HL$hT*PIE1Wf. t  t  LHA HT$HJH9HL$LffHJH9HL$L*ɉHHJH9HL$T*ffPIE1f.(LH HL$HQH9HT$kt H H9YHH0HPHQH9HT$=t H H9+HHpHPHQH9HT$T P IE18LHI HT$HBH9HD$DAHD$HPH9HT$DH<$INHt$LD$LAFHT$HBH9HD$gTʉHH9RHINIF HBH9HD$5TʉH H9 HIV(IF0Mu1f22 2LLHHL$HQH9HT$t H H9HH0HPHQH9HT$T ʉPHQH9HT$nT)ʉPIE1_f@LHIvHD$HPH9HT$(TffAHPH9HT$ L(HH9HINIVHPH9HT$DIN0ƒAVAVAV AF(AV$LHHL$HQH9HT$iT ffIE1W(LHsHL$HQH9HT$%t H H9HH0HPHQH9HT$T уHHHP HIE1(LHHT$HJH9HL$LffHJH9HL$kt*HH9YHHpHHHJH9HL$<TуHP HIE1fZZZLHLHIHD$HPH9HT$TffAHPH9HT$D(H H9wIFHAHIVH9HD$ZL HH9HHINIF HBH9HD$+DƒAV(AV,AF4AV08LHHL$HQH9HT$HL HH H ʉH HHL$HQH9HT$T PHQH9HT$st)H H9aHHpHPHQH9HT$Dt H H92HHp HP(HQH9HT$T ʉP0IE1LH"HL$HQH9HT$t H H9HH0HPHQH9HT$T PIE1<<F<2<8LHHT$HJH9HL$7LffHJH9HL$T*H4 H9HPHVHHHH9HT$t5H H9HHpHP HQH9HT$L H4H9HHH(HP0IE10LHHT$HJH9HL$cLffHJH9HL$ET*H4 H93HPHVHHHH9HT$t5H H9HHpHP HQH9HT$T H(P,IE1@LHHL$HQH9HT$t H H9HH0HPHQH9HT$lHt HH H ʉH HPHQ H9HT$=T)PHQ H9HT$ t) H H9HHp HP(HQH9HT$L H4H9HHH0HP8IE1H\$Hl$HLd$Ll$ILt$L|$HXHL$IMH$1ɸ1H9HD$w6ELHfAEAD Auԃ fPv; @H\$(Hl$0Ld$8Ll$@Lt$HL|$PHX$fDLH(IE1륾LHI^(t9HT$HBH9HD$fAH H9HL$OLIWIG@t9HT$HBH9HD$%AH H9HL$LIWIG t HT$HBH9HD$AAG8t HT$HBH9HD$AAG9t9HT$HBH9HD$AH H9HL$qLIW@IGHt9HT$HBH9HD$GA HH9HT$0LIOPIGXt9HT$HBH9HD$AH H9HL$LIW`IGh@ŀt9HT$HBH9HD$AH H9HL$LIWpIGx@@t6HT$HBH9HD$IHH H ȉH I@ t?HT$HBH9HD$LAH H9HL$5LII@t?HT$HBH9HD$AH H9HL$LII@t?HT$HBH9HD$AH H9HL$LIIt:HT$HBH9HD$~AH H9lLIIM}1UH<$Ht$IO(LD$L7.@ ff.H\$Hl$HLd$H82HIH$HL$HD$G<@  U(d<V P<Z<.H<H$HUHL$HHUHuHzH9H|$pHyD$i(( fJ (v@ W ,)L@H\$ Hl$(Ld$0H8@<V22f(2)2t2uH<$UHD$ʉ눁( |6  f: H BHH<$Ht$HL$,HT$H$HMLd$HBH9HD$jfD 2  ((3(t(fD1ZZs Ut܁ Z1fD(<D6< < <BD  ^ 2 j3 V) [DH<$EA$HEfHfA$HEAD$HUHuHBH9HD$I|$HT$HMHBH9HD$pA HUHD$Hu H H9HL$MI<HT$HM(HBH9HD$)A HU(HD$Hu0H H9HL$I<HD$DE8HPEH9HT$HU@A H<$Ht$HL$ID$DHEfHfA$HEAD$HUHuHBH9HD$lI|$HL$EHQH9HT$GffA HT$EHJH9HL$#ffAD$Z1f.HHHH HH H I$DVEHH AD$HD$ HFAD$ HVHL$HvH H9HD$tI< HD$HM HPH9HT$PA HD$HU Hu(H H9HL$-I<HT$M0HBH9HD$ A D$HfHfHFAHVHvHBH9HD$HyHT$HMHBH9HD$A HD$HUHu H H9HL$rI<}(DE,DM0DU4ƒEE‰ƒEE‰ƒEEHT$HJH9HL$AHU8D@ywDrwDrgD`bwDr9D@tCDP~4oDjP+D fh~Dy2D@m!D \ D [ D [ D [%D `.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rodata.str1.8.rela.rodata.comment.note.GNU-stack.rela.eh_frame @C`&D,D12D^@2xK(TLOr0\0Q+eQzQu TxY   ]y   #U? P+hI{`e!E 9>5 2@>!Dp>Z?>o@?w?w@@g@w0A9pACAo0B+`B~B2# C!6PC EpC TC eC%amqp_framing.camqp_constant_nameamqp_constant_is_hard_erroramqp_method_nameamqp_method_has_contentamqp_decode_methodamqp_pool_allocamqp_decode_tableamqp_decode_propertiesamqp_encode_methodmemcpyamqp_encode_tableamqp_encode_propertiesamqp_channel_openamqp_empty_bytesamqp_simple_rpc_decodedamqp_channel_flowamqp_exchange_declareamqp_exchange_deleteamqp_exchange_bindamqp_exchange_unbindamqp_queue_declareamqp_queue_bindamqp_queue_purgeamqp_queue_deleteamqp_queue_unbindamqp_basic_qosamqp_basic_consumeamqp_basic_cancelamqp_basic_recoveramqp_tx_selectamqp_tx_commitamqp_tx_rollbackamqp_confirm_select  h) < I IV o ]~     0 A S $ 4 l' 8 A T b w {   ' G6 I %\ o |  @       * A JR cc -w @ y \  h S  5 / F W o   -   z  _ ( 9 O `  q  p    -   ! 7 H Y o $ H   ` } Fo      I  ia9S)=kI1 Z )I!"#%%&K&&''\((D))|** +D++E,,,L--//001b12V33,4s45X5566w7[8889 U:::;;6<<<8=T==>">,>X>>5??.@@A`AA&BRBB C8CgCCCC  (08@HP X`hpx   (08@ HPX`hpx@ (08@HPX `hpx <999999999<99999999 9(<0989@9H9P9X9`9h9p9x<999999999<9999999999 9(90989@9H9P9X9`9h9p9x9999999999999<9999< 4H \p`! 98>P@>hp>?@??@@@0A pA8AT0Bl`BB CPCpCCCamqp_api.c.o/ 1380622528 1000 1000 100664 6928 ` ELF>P @@ H@HtFsHwHHtHwH@HwH@1)Ht9rHtDHwH<HwH<HwH<HHt$(HT$0HL$8LD$@LL$Ht7)D$P)L$`)T$p)$)$)$)$)$H$HH=HL$D$HD$HD$ D$ 0HD$H5 ffffff.AWAVAAUATIUSHXD$L$H$HT$XHL$`LD$hD$x$LL$pfD$PD$|~H'I;$ HL$P(<LMHt$ LD$ f\$"fD$(<Hl$0L|$8xhHAL$H1McH9ssHH)tkL9IHt$ IGLD$ HfDt$"HT$0HD$(yHX[]A\A]A^A_DHLt?fD1@H$LHIHf뚸fH\$Hl$HLd$HhAH|$0HAdH%(HD$H1fL$ H|$ $)D$LL$HAI(HHHD$fD$(fD$*HT$HdH3%(uHHl$XH\$PLd$`HhfUAHSHHXH|$0fT$ dH%(HD$H1H|$ $3 D$LL$H1I2 HHHD$fD$(fD$*HT$HdH3%(u HXH[]HH$L$P<HHffffff.UHSHHhLD$PDL$XLD$0LL$@HL$HHF<D$0G<D$4H<D$8fD$@H4$HHL$H3HHT$HKHHD$HSHHCHhH[]@HH$L$Z<HH(unknown error)%dcould not allocate memoryinvalid AMQP dataunknown AMQP class idunknown AMQP method idhostname lookup failedincompatible AMQP versioncould not parse AMQP URLa socket error occurredinvalid parametertable too large for bufferunexpected method receivedrequest timed outsystem timer has faileda SSL error occurredSSL handshake failedoperation completed successfullyconnection closed unexpectedlyheartbeat timeout, connection closedsocket library initialization failedSSL hostname verification failedSSL peer cert verification failedGCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx l0DGL\BBE B(D0A8I/ 8A0A(B BBBF JLp A (AQGp{ DAA !D \(AGGDA@!D \.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.rela.rodata.rodata.str1.8.comment.note.GNU-stack.rela.eh_frame @&,12jE` @(M2`\0B +em zp Xu8  P  @ 1   ClVphq|`.? U!ds! amqp_api.cbase_error_stringsssl_error_stringstcp_error_stringsamqp_error_string2amqp_error_string__strdupamqp_abortstderr__vfprintf_chkfputcabortamqp_basic_publishamqp_get_monotonic_timestampamqp_send_methodamqp_send_frameamqp_try_recvamqp_channel_close__sprintf_chkamqp_simple_rpc__stack_chk_failamqp_connection_closeamqp_basic_ackamqp_basic_getamqp_basic_rejectamqp_empty_arrayamqp_empty_tableamqp_empty_bytes # @5 E O ] g   @   YH ( m@@ HP-X?`Uhlpx (( H p@  U 4pH`` D/18 1380622528 1000 1000 100664 7952 ` ELF>(@@ S0HHHǀǀǀHǀHtuHHHǃǃHǃHHǃHHt H[@1H1H[H11ff.HHt fSHt H[8H1ffff.H\$Hl$HHHHHH\$Hl$Hf.HUSHHɉ~3HtWHcHiʚ;Hi5wHHH(H HHcHHtH1H[]11@fAUIATUSHHtkE1K\%Ht"fDH{H+HHHuIIuIIILH1[]A\A]fDHl$Ld$HH\$Ll$ILt$L|$HXHH4$HT$Hu LJHHIL|$H)H9LLFHLLHHH9HL|1D'tA$HHǃHǃHǃǃHDH\$(Hl$0Ld$8Ll$@Lt$HL|$PHXfD1@LVAvHfHAvHH΃HHHL)K4/fHPHHLǃH)H9HGLHIHHHH9HA|θAHA$AvffAt$HA$NSA~IN MD$HA|$HH )`A$AfAD$AFAD$AFAD$ AFAD$ AFAD$ fDHIMt$HID$fA~MD$HffA|$IN HH H ʉH INIT$HIL$(HIT$ f@1fAUIATUSHLHH]HtAAsHu#IHu ;HHt0HPf;ruHHuHL9uH[]A\A]f.LHtHHHu11AUIATUSHDEt H[]A\A]LHfH]HtAAsHu#IHu 3HHt(HPf;ruHHuHL9uH[]A\A]fLHtHHHuːHDEuPHHt&HPf9ru6fDHPf9Jt&HHuHtHHDHff.ATUHSHPHFffC<B<<t<AttHPD[]A\E1DcHHADE~H?HcHiʚ;HH(HPD[]A\FHK ȉCHHF~H HA[AIcAHBH]FfC HKffCHVHH H ȉH HC HHF~HHAA IcAHBHHFD$ȉCHFHH\$ HD$(HD$HHD$0HFHt$ HD$8HD$HD$@AAiProgramming error: invalid AMQP connection state: expected %d, got %dInternal error: invalid amqp_connection_state_t->state %d%sAMQPGCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx  A E U A @T3AR E p6JG d(ACG  AAD 4BEA A(D0t(C ABB(J^`) G D8XBEA A(D0r (A ABBK LBEA A(D0P (A ABBA c (A ABBC eDR J DDBAD Dp}  DABA ]  DABD .symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.comment.note.GNU-stack.rela.eh_frame @k ( & , 12 @22 O0: +Xe mh HhP  w  @ '.6=BM]t 3`62`Gp_o2Dp_ eamqp_connection.camqp_new_connectioncallocreallocmallocfreeamqp_abortamqp_get_sockfdamqp_socket_get_sockfdamqp_set_sockfdamqp_tcp_socket_newamqp_tcp_socket_set_sockfd__errno_locationstrerroramqp_set_socketamqp_socket_deleteamqp_get_socketamqp_tune_connectionamqp_get_monotonic_timestampamqp_get_channel_maxamqp_destroy_connectionempty_amqp_poolamqp_handle_inputmemcpymemcmpamqp_get_or_create_channel_poolamqp_pool_alloc_bytesamqp_decode_methodamqp_decode_propertiesamqp_release_buffers_okamqp_release_buffersamqp_get_channel_poolrecycle_amqp_poolamqp_maybe_release_buffersamqp_maybe_release_buffers_on_channelamqp_send_frameamqp_socket_sendamqp_encode_methodamqp_encode_propertiesamqp_socket_writev  `   $9@E O|$ Q X  Hf n!"# q"$%D(Q)b i()f( - j . /S 0 4w) DX t``pH\p amqp_mem.c.o/ 1380622528 1000 1000 100664 4568 ` ELF>@@ f.f.HGHDHGGH7HG G(HG0HG8ff.AUIATLgU1S1HG~@ID$H<(HA;$|I} HtAEIE AE(IE0IE8H[]A\A]@AUIATLgU1S1HO~@ID$H<(HA;$|I} HtAU11AEIE MeAE(IE0IE8~"ID$H<(HA;$|I}HtAEIEH[]A\A]@H\$Hl$Ld$Ll$Lt$H(HHnH7HHH9wwHG0HtLg8JT%H9sPLccC(D9HSHcȃL$ʉC(Lc0Hk8LH$Hl$Ld$Ll$Lt$ H(IHW8HHItSHckH{ DmIcHHt#Ht1HckHC DmL$DkyHHHC uE1YHIHC0tEl$H{IcHHt,HtLccHCEl$N4DkDk(Lc0HHHCufDSH2HHC[fffff.SHH H H[f.H\$Hl$HHHHt$HHtHt$HHHHH\$8Hl$@HHSHH H HH[HAUATIUSIAHJ,Htf9uHHf9PHtoHHuPHtlIc$fXHH(K@H@@ H@(H@0H@8HDH@@HPHH[]A\A]H1HHHt$f9pHuf9PHt HHuH10.4.1GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx 0DE4X|BEE C(F0`(A ABB4BEE C(F0(A ABB$]0{ H AP AG0ID,HNPyHAG0IGh8|BBD A(M0 (A ABBA 8.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.1.comment.note.GNU-stack.rela.eh_frame @ &H,H12H@0N+Iy^Y8 Hh    . - E<p|NScszPpH8amqp_mem.camqp_versionamqp_version_numberinit_amqp_poolrecycle_amqp_poolfreeempty_amqp_poolamqp_pool_alloccallocreallocmallocamqp_pool_alloc_bytesamqp_cstring_bytesstrlenamqp_bytes_malloc_dupmemcpyamqp_bytes_mallocamqp_bytes_freeamqp_get_or_create_channel_poolamqp_get_channel_pool   ! 5   y ;XyT 4H \pPp0Llamqp_socket.c.o/1380622528 1000 1000 100664 18176 ` ELF>P(@@ AWIAVAUATUSH(HH|$Ht$9»LcALd$ H$ 1ۉT$ ?)I@LHLL l HHL|$ 1MHLL Ġ,u8&HIWI7HiHiʚ;HHT$H9HH)HSZ/DHH HHS㥛 H IHiʚ;H)HHHHIWHT$HHHH1HPxUHT$H1HHǂ~0HtEHL$HcHi5wHH fH([]A\A]A^A_@ڻU11SHx4u(Hc1x1H[]HcָfAWE1AVISZ/DAUIS㥛 ATE1U1SHHhHHt$HH9GDEHHDEL(L9H H9s H HL9MLd$LFLH)HH HIH HT$Hiʚ;H)HHHIHHT$LHHL9 ML;($11@Ht$0HfD$2D$0u{HHt~~L(HHL$H)HHt$ HHT$(x(HHHL$HtS\1Hh[]A\A]A^A_ÐfuH)HHP @1HHfHHAUA!ATUHSHH\$ D$ dH%(HD$x1HHH|$PD$(D$,HL$Ht$PHHWH\$HSS s{Ǿ1Hc1HL$ AuDSHsu2H|$HT$xdH3%(HĈ[]A\A]@H[(Htg>2fsH[(HH|$fD(IĉE,$H|$u@Q@61%ff.HHHH@HH@H1H@DHH@HH@ Ht HH@0ffffff.HH@([ff.AWAAVAUATIUHSHdH%(H$1HD$0HD$pHD$xtH:HzH$1!HHH$DŽ$DŽ$HL$`H$HLLl$`MH$L$HT$DAU AuA}EǾ1Hc1HL$0A-HT11 Hc1AUIuQ8sHD$ ؍SALcT$, ?)H$PIHD$1ҾH|$HHLT$H4$T$H4$L H|$HHLH|$pHL P|$,H$PH$1MLD$PHL$@D$PDT$@E11 Hc11H|$`D$݉D$tH$dH3%(H[]A\A]A^A_Mm(MfD&HD$ 8n@Mm(MVE9fAUIuuH|$`@fDD0IĉE4$VD11pHc1TH|$`$H|$`D$D$1H|$`ݻ\af.HHHPH1HfHH9ff.AUATIUSHHXHfHH9HHL$ HH)HHcH|$ Htt$"HHI0HLHHHHT$ HUHT$(HUHT$0HUHT$8HUHT$@HU HT$HHU(HHHhHtQHHHHH9HLHH$HD$1HX[]A\A]DHHX[]A\A]H\$Ld$HLl$Hl$H(vIHIH0LHHHHHHSHPHSHPHSHPHS HP HS(HP(I$HEt9I$H(HE1I$H\$Hl$Ld$Ll$ H(I$fD͐AVAUATAUHSHHHtLHHf9qu@HHfD9aHHu HL(IELHH sfD9HHIH0LIHMHHHSHPHSHPHSHPHS HP HS(HP(HIECLAHHHtQHHHAHCHAHCHAHCHA HC HA(HC(1[]A\A]A^[]A\A]A^fHDžHHtTHBHHHt1HHHPHVHPHVHPHVHP HV H@(HF(1HLJff.H\$Hl$HLl$Ld$ILt$L|$HHHHHBHHHtgHHUHPHUHPHUHPHUHP HU H@(HE(1H\$hHl$pLd$xL$L$L$HĘHLJMtI}kI}`HHD$E1E1E1HH9@M7HIh~ L;(MMuM]M}MiIiʚ;IMM9M~3H I9v L LL(L9MLFMtM9MGLHSZ/DL)HH HHS㥛 H HT$Hiʚ;H)HHHHD$HD$HHT$HT$LHL9 M9L;(1Ht$0HfD$2D$0HI@HH)HHHt$ HHT$(HHHUtJ1fDxHHHP U1HH5&1f.USHHHLMI8I@HHtjH0Ht$HpHt$HxH|$ HxH|$(Hx H|$0H@(HD$8f9l$u>|$u79T$u1HD$HHD$ HA1HH[]HǃHHP HH[]Ht$T$H $6T$H $uxDH8ft$H$T$HL$H8ffff.AWAVAAUIATMUHHSHHt$PH$HD$HD$HD$D$PfT$RL$XLL$`yHHHt$ Hi|$ t$"ufD9fuL$(2 HHI0HLHHHHHD$ HHD$(HCHD$0HCHD$8HCHD$@HC HD$HHC(HHHZH H@A<$L$(t"9L 9t$Hu( 9IA$u$H$IEHD$(IEHD$0IEHD$IE4f$D$H$IEHD$IEHD$IEHD$IEHĈL[]A\A]A^A_f$D$A<$t9[_Uffffff.H\$Hl$HLd$Ll$ELt$L|$HHHT$(IAEͺHPE1E1ALD$H$D$$LkH$HH$L$L$L$L$HCH$HCHH$HfHL$p1 Lx(HD$xf8 t,E1E1Aheartbeat == 0Internal error: unable to determine timeout reasonSee https://github.com/alanxz/rabbitmq-c%dInvalid SASL method: %dproductrabbitmq-cinformationPLAINen_USAMQP GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx L BEB B(A0A8G 8C0A(B BBBE (lWALF k AAH L>BEL L(D0C8G 8A0A(B BBBB DK<BTA D(G (A ABBE @Th |     LBEB B(D0D8G( 8A0A(B BBBD X D[pHpBBD A(G4 (A ABBF T(F ABB JQ0 D LBBB D(D0R (A BBBI A (A BBGC Xe(lfJMT H 4ACG` AAH a FAH #D@^LaBBE E(D0G8G 8D0A(B BBBJ (8XJMT J dpAM@`A/ AJD$AJD.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rodata.str1.1.rodata.comment.note.GNU-stack.rela.eh_frame @!70 &!,!12!@2q"FO"W0"+`"u"pD ', 3 !W=p>ZX   F[iu|    '  90LP c`tp@ ` p  p"3Uelf`P#a+@UPpm/ amqp_socket.crecv_with_timeoutamqp_os_socket_setsockblockwait_frame_inner.constprop.4amqp_open_socket_noblock.constprop.5header.6282amqp_login_inneramqp_get_sockfd__fdelt_chkselect__errno_locationamqp_get_monotonic_timestampfcntlamqp_abortamqp_send_frameamqp_handle_inputamqp_maybe_release_buffers_on_channelamqp_os_socket_error__sprintf_chkgetaddrinfosocketsetsockoptconnectfreeaddrinfoclose__stack_chk_failamqp_os_socket_closeamqp_socket_writevamqp_socket_sendamqp_socket_recvamqp_socket_openamqp_socket_open_noblockamqp_socket_closeamqp_socket_deleteamqp_socket_get_sockfdamqp_open_socketamqp_open_socket_noblockamqp_timer_updategetsockoptamqp_send_headeramqp_frames_enqueuedamqp_data_in_bufferamqp_try_recvamqp_get_or_create_channel_poolamqp_pool_allocamqp_queue_frameamqp_simple_wait_frame_on_channelamqp_simple_wait_frameamqp_simple_wait_frame_noblockamqp_simple_wait_methodamqp_send_methodamqp_simple_rpcamqp_maybe_release_buffersstrlenamqp_pool_alloc_bytesmemcpyamqp_cstring_bytesamqp_release_buffersamqp_tune_connectionamqp_table_entry_cmpamqp_simple_rpc_decodedamqp_get_rpc_replyamqp_loginamqp_empty_tableamqp_login_with_properties($@ @    5Zr !"A!Q^"v!"!# ,m   (    /  0> Z v ! " ";  I !Y f "   ! ! !! !2 #Q  5 6, 6#5<6L6~566 4 @;er#K Rj>5W6g66 Z>;65W ^???@GAiA B #B .B xBa :m @C;'DzCB=X?6EEz=P I" ppDXl 0P` p\@ t` p   \p`P<hP amqp_table.c.o/ 1380622529 1000 1000 100664 12200 ` ELF>@@ AWAVAUIATUSLHHM8HL$(Ht$HT$ H|$0IoHt$8H9I(F4>L$HIċL$AlEII9Lt$bIWI9HHt$E1AL7E1kf.HT$K 4H|$0IH1Ht$8HQHT$ H5xDAHH9D$HPL9Hw!Ht$D9 ~CI(H2L9HvLL$L$HH[]A\A]A^A_f.LL$HcH4HHL$tYHIDMcHD$(H|$ KHD8HHT$(HHBnHLH1YOUHt$(H|$ 11HT$(HBfff.Ld$Ll$IH\$Hl$MLt$L|$HxIH|$ Ht$(HBH9IwIψA<7v/H\$HHl$PLd$XLl$`Lt$hL|$pHx$fDIHBH9IwHHH H ȉH HA1뗐IHBH9IwȉA1xfIHBH9I^ffA1Pf.IHBH9I.A1%IHBH9I ʉH H9IHIWIG1IHBH9I1<A1IH|$0Ht$8HQH9IHT$HIHT$_11HD$H9HD$rLGfDHD$I;E;\$|%d$LHcD$H4@HHIHH|$0Ht$8I .MLyLD$D$LH|$ Ht$(H\$HHl$PHILd$XLl$`Lt$hL|$pHxIHBH9IAIHBH9IyȉA 1o1hA_HcLH[HHHIGHAHL1/%LAG11HIGfAWAVIAUIATUHSHH8HH|$ Ht$(HD$HHD$HHE0HD$HH9HsfDH8[]A\A]A^A_@HL$A(E1E1'DHEH IW(B48HAI9HrMIA4HEH;LHHpHI9HrLLT$LT$LUHH|$ Ht$(IRQ^AD9e{HL9l$=+D$HT$AH81[]A\A]A^A_f.H\$Hl$HLd$Ll$Lt$L|$HXLD H<$Ht$IHH9H v*H\$(Hl$0Ld$8Ll$@Lt$HL|$PHXF A<7v $fDHJHHBH9Hf.JHHBH9Hw1 hfJHHBH9Hw 1IJHHBH9Hwff1"@HH<$Ht$H\$(Hl$0HLd$8Ll$@Lt$HL|$PHXH DBHAH9H7DJ ?@H$L+LzJHD$HD$MeL#HD$1E1IWH|$HHt$H'eAHE;7|H L9d$HT$@D)AB*1-JHHBH9Hy1DH LBHAH9HPADHJLBHH H9H.H<HL1fHH H ȉH H11L"H\$Hl$HHH/HvHH9HHF)H\$DHl$Hffffff.AWAVAUIATUSHHcH|$u)HHHHF1H[]A\A]A^A_H4HIHHHIEAuHD$LxI7Hti(E1LHH{Ht|IwHHsILpnAE9e~6HT$I]LzHIH(I7HuH[]A\A]A^A_H1[]A\A]A^A_ fDH\$Hl$HLd$Ll$H(HA<7v&H\$Hl$Ld$Ll$ H(I$GF1fDHGHF1@GfF1@GF1D1@G1FwG1F_HHcGH׉FH4@HHHC{E1DAD$I9CvHCK0+G\W/ fp  ^&>  Ugns{pF A * amqp_table.camqp_decode_field_valueamqp_encode_field_valueamqp_field_value_cloneamqp_decode_tablemallocfreereallocamqp_pool_allocmemcpyamqp_encode_tableamqp_table_entry_cmpmemcmpamqp_table_cloneamqp_empty_tableamqp_pool_alloc_bytesamqp_empty_bytesamqp_empty_arrayS -e  =v4_LN L    7 w  i           a a(0a8a@HaPaX`ahapaxaaaAaaaaaaaaaaaa a a(0a8a@HaPaX`ahapaxaaa}aaAH> >>>>>X >(>0>8>@>H>P XX`>h p>x>>>>>>>>>>>X>>>>>X >(>0>8>@>H>PX`h>p>x   :  : ` : : p : :  : : : : : :   : ( 0: 8: @: H: P: X: `: h: p: x: :  :  :  : : p : :  : : : : : :  p  (: 0: 8 pp8 T  amqp_url.c.o/ 1380622529 1000 1000 100664 4312 ` ELF> @@ HHGHGG (HGG$fAWHIHAVAUATUSHHt3HAG 'AG$AfDA$MIIMuMA$IFIl$:t%X2rfE1:L@[ A}:Mt9Ht$0 LHT$0I9S:JH=>AG /Q)HH1[]A\A]A^A_?}{A^II:MosLmIA$IEI|$:%fD#A]II@[]jDHL$ HT$1H|$ D$IAF'?O@ffDA>HH[]A\A]A^A_@MM/tMgLmIA$IEI|$:t"L%+f[IE1HfDL9w8nH]IAEHSMu<:<%@<]'MFIoMA]I@Im:%#fAXI@<[t<]tCMH:<@tH@@ Gfff.H\$Hl$HH1tuCH\$Hl$H@fSHHHx C1[@C[AUIATIUSHH{LLH}"C tHH[]A\A]HHDH[]A\A]f.AWAVDrAUATUHSHEHt$IE1I$M|$DI9tKHI)Nj}LHHyE tHH[]A\A]A^A_f.AIE E9uMcIL|$MM'I_@H9t0IH)Ë}@HLHyE t{E H1[]A\A]A^A_E1fffff.HSHt/tuCH{H[D[fDATIUHSH H9t;HH)A|$@HHHyAD$ t[]HA\[]AD$ 1A\H\$Hl$(HHHHtH@HHHHl$H\$Hffff.H?uwPH1<%p> is not of type amqp_tcp_socket_tGCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx 0GJG j E P)AZ E HHpfBED C(G0j (H ABBD O(A ABB`BBF B(A0D8DP_ 8H0A(B BBBK p 8C0A(B BBBA  :Dj J A4@`BDD { AIA AAMxSS N.symtab.strtab.shstrtab.rela.text.data.bss.rodata.str1.8.rela.rodata.comment.note.GNU-stack.rela.eh_frame @=0 &,12&E8 @ M0+V#k(f u   j.GD`)Yfn :``8  S-4D _amqp_tcp_socket.camqp_tcp_socket_get_sockfdamqp_tcp_socket_closeamqp_tcp_socket_openamqp_tcp_socket_recvamqp_tcp_socket_writevamqp_tcp_socket_deleteamqp_tcp_socket_sendamqp_tcp_socket_classamqp_os_socket_closeamqp_open_socket_noblockrecvamqp_os_socket_errorsendfreeamqp_tcp_socket_newcallocamqp_set_socketamqp_tcp_socket_set_sockfdamqp_abort,mZd2F # 4 9O`` (0  4T`t$ D`| amqp_timer.c.o/ 1380622529 1000 1000 100664 1888 ` ELF>@@ HHtH$Hiʚ;HD$HD1HfUSHHH?uaHHL$Iiʚ;HL$HH HuH}Hiʚ;HiHHHS8f.Ht~H$Hiʚ;HL$HH tmHSH9ѸwNH)HHHSH HSZ/DHH HSHiʚ;H)HS㥛 HHH1HHS H[]HH[]GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx 7D f F F4<AAG0 AAD KFA.symtab.strtab.shstrtab.rela.text.data.bss.comment.note.GNU-stack.rela.eh_frame @SH &,10+:OpJ00 0Y  K7+9@amqp_timer.camqp_get_monotonic_timestampclock_gettimeamqp_timer_update  [  @@/60 1380622529 1000 1000 100664 6720 ` ELF> @@ SHHHH[fff.SHH HHH{8Hs@H{(Hs0H{Hs[DH\$Hl$HL|$Ld$HLl$Lt$HIHD$HD$HD$ HHD$(A\@j@xD1AHt HAt fHAtDHT$0HDteD$D$(HD$Hl$pLd$xL$L$L$HHD$HCHD$ HCHD$(HCHH\$hHĘ@D$0<tg<u;D$8=2 t=(u)HD$8D$HD$HD$@HD$ gHt$0HD$D$(=fDIHHD$ALl$HLK@b@F1HAAEĀAt#IuHHIWHIW@t#IuHHIWHIW t AU8AW8t AU9AW9t#Iu@HHIW@HIWHt#IuPHHIWPHIWXt#Iu`HHIW`HIWht#IupHHIWpHIWx@tII t,IHHIHIt,IHHIHIt,IHHIHIt,IHHIHIH|$@HlHL5IME1IuTfDD$0<HT$8IDI;LHt$@LHD$8IIM9NHT$0DHtD$D$(IIH|$DHyA@@fHA@AHuDfHf.HHT$Iw(I}(AfDHIIID$D$(3@D$D$(H|$IIHtpIIH|$IWIHtAIuIWAH|$IWI HtIu IWAD$D$(QH|$IW@IHHtIuHIW@AH|$IWPIXHtIuXIWPAH|$IW`IhHwIuhIW`AH|$IWpIxHGIuxIWpA H|$IIHIIAH|$IIHIIAH|$IIHIIAD$<D$8=2 t =(HD$8D$HD$HD$@HD$ AIHfHff.Hl$HH\$Ld$Ll$H@HIHHD$ HD$(HD$0HD$8HA`@@D1AHt HAt fHAtHt$@LtZD$ D$8HD$ HHD$(HCHD$0HCHD$8HCHH$H\$xL$L$HĘ|$@t)Ht$@LD$ D$8f.|$H<<uLl$PD$BI}IufEHEIEI} Iu(HUHEAEE I}0Iu8HE(HU0H}HE8HU@H}0HUHMHE1LHH$Ht$HL$HT$HD$ Ht$(HL$0HT$8H}8Hu@H}(Hu0H}HuffHA@fAHDEH}A_D$ D$8nD$ HD$ HsHKHSH'GCC: (Ubuntu/Linaro 4.7.3-1ubuntu1) 4.7.3zRx $A^8KAE(TEJa E (EY D .symtab.strtab.shstrtab.rela.text.data.bss.comment.note.GNU-stack.rela.eh_frame @ H & , 10 +: O J`  Y@  HK$&6F0K\En5amqp_consumer.camqp_destroy_messageempty_amqp_poolamqp_bytes_freeamqp_destroy_envelopeamqp_read_messageamqp_simple_wait_frame_on_channelamqp_queue_frameinit_amqp_poolamqp_empty_bytesmemcpyamqp_table_cloneamqp_bytes_mallocamqp_pool_alloc_bytesamqp_consume_messageamqp_simple_wait_frame_noblockamqp_bytes_malloc_dup  < O \ i ; -:Ebm%3Uc ( 2 Edw'=Wm;~  1 U j       w <0X././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/murano-agent.c0000664000175000017500000002022100000000000022576 0ustar00zuulzuul00000000000000#include #include #include #include #include #include #include #include #include #include #include #include #include "utils.h" #include "lcfg_static.h" static void run ( amqp_connection_state_t conn, int log_fd , const char *result_routing_key ) { int received = 0; amqp_frame_t frame; while ( 1 ) { amqp_rpc_reply_t ret; amqp_envelope_t envelope; amqp_maybe_release_buffers ( conn ); ret = amqp_consume_message ( conn, &envelope, NULL, 0 ); if ( AMQP_RESPONSE_NORMAL == ret.reply_type ) { int i; amqp_bytes_t body = envelope.message.body; const char *title = "A new message received:\n"; fprintf ( stdout, title, received ); for ( i = 0; i < body.len; i++ ) { fprintf ( stdout, "%c", * ( char* ) ( body.bytes + i ) ); } puts ( "\n" ); write ( log_fd, ( void * ) title, strlen ( title ) ); write ( log_fd, body.bytes, body.len ); write ( log_fd, ( void * ) "\n\n", 2 ); /* Send a reply. */ amqp_basic_properties_t props; props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_MESSAGE_ID_FLAG; printf("message id: %s", (const char*)envelope.message.properties.message_id.bytes); props.message_id = amqp_bytes_malloc_dup ( envelope.message.properties.message_id ); props.content_type = amqp_cstring_bytes ( "text/json" ); props.delivery_mode = 2; /* persistent delivery mode */ const char *result_body = "{\"IsException\": false, \"Result\": [{\"IsException\": false, \"Result\": []}]}"; die_on_error ( amqp_basic_publish ( conn, 1, amqp_cstring_bytes ( "" ), amqp_cstring_bytes ( result_routing_key ), 0, 0, &props, amqp_cstring_bytes ( result_body ) ), "Publishing" ); amqp_destroy_envelope ( &envelope ); } else { if ( AMQP_RESPONSE_LIBRARY_EXCEPTION == ret.reply_type && AMQP_STATUS_UNEXPECTED_STATE == ret.library_error ) { if ( AMQP_STATUS_OK != amqp_simple_wait_frame ( conn, &frame ) ) { return; } if ( AMQP_FRAME_METHOD == frame.frame_type ) { switch ( frame.payload.method.id ) { case AMQP_BASIC_ACK_METHOD: /* if we've turned publisher confirms on, and we've published a message * here is a message being confirmed */ break; case AMQP_BASIC_RETURN_METHOD: /* if a published message couldn't be routed and the mandatory flag was set * this is what would be returned. The message then needs to be read. */ { amqp_message_t message; ret = amqp_read_message ( conn, frame.channel, &message, 0 ); if ( AMQP_RESPONSE_NORMAL != ret.reply_type ) { return; } amqp_destroy_message ( &message ); } break; case AMQP_CHANNEL_CLOSE_METHOD: /* a channel.close method happens when a channel exception occurs, this * can happen by publishing to an exchange that doesn't exist for example * * In this case you would need to open another channel redeclare any queues * that were declared auto-delete, and restart any consumers that were attached * to the previous channel */ return; case AMQP_CONNECTION_CLOSE_METHOD: /* a connection.close method happens when a connection exception occurs, * this can happen by trying to use a channel that isn't open for example. * * In this case the whole connection must be restarted. */ return; default: fprintf ( stderr ,"An unexpected method was received %d\n", frame.payload.method.id ); return; } } } } received++; } } static const char* get_config_value ( struct lcfg *cfg, const char *key, int verbose ) { void *data; size_t len; if ( lcfg_value_get ( cfg, key, &data, &len ) != lcfg_status_ok ) { fprintf ( stderr, "Key %s is not found in the configuration file", key ); } const char *val = ( const char * ) data; if ( verbose ) { fprintf ( stdout, "%s = %s\n", key, val ); } return val; } int main ( int argc, char const *const *argv ) { if ( argc != 3 ) { printf ( "usage: %s CFG_FILE LOG_FILE\n", argv[0] ); return -1; } const char *log_filename = argv[2]; int flags = O_CREAT | O_APPEND | O_RDWR; mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP; int log_fd = open ( log_filename, flags, mode ); if ( log_fd < 0 ) { fprintf ( stderr, "ERROR: Falied to open the log file '%s'\n", log_filename ); exit ( 1 ); } /* Read the configuration file. */ struct lcfg *cfg = lcfg_new ( argv[1] ); if ( lcfg_parse ( cfg ) != lcfg_status_ok ) { printf ( "lcfg error: %s\n", lcfg_error_get ( cfg ) ); return -1; } /* Read all the configuration parameters. */ fprintf ( stdout, "Starting Murano agent with the following configuration:\n\n" ); const char *host = get_config_value ( cfg, "RABBITMQ_HOST" , 1 ); int port = atoi ( get_config_value ( cfg, "RABBITMQ_PORT" , 1 ) ); const char *vhost = get_config_value ( cfg, "RABBITMQ_VHOST" , 1 ); const char *username = get_config_value ( cfg, "RABBITMQ_USERNAME" , 1 ); const char *password = get_config_value ( cfg, "RABBITMQ_PASSWORD" , 1 ); const char *queuename = get_config_value ( cfg, "RABBITMQ_INPUT_QUEUE" , 1 ); const char *result_routing_key = get_config_value ( cfg, "RABBITMQ_RESULT_ROUTING_KEY", 1 ); amqp_connection_state_t conn = amqp_new_connection(); amqp_socket_t *socket = NULL; amqp_bytes_t queuename_bytes = amqp_cstring_bytes ( queuename ); socket = amqp_tcp_socket_new ( conn ); if ( !socket ) { die ( "creating TCP socket" ); } if ( amqp_socket_open ( socket, host, port ) ) { die ( "opening TCP socket" ); } die_on_amqp_error ( amqp_login ( conn, vhost, 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, username, password ), "Logging in" ); amqp_channel_open ( conn, 1 ); die_on_amqp_error ( amqp_get_rpc_reply ( conn ), "Opening channel" ); amqp_basic_consume ( conn, 1, queuename_bytes, amqp_empty_bytes, 0, 1, 0, amqp_empty_table ); die_on_amqp_error ( amqp_get_rpc_reply ( conn ), "Consuming" ); puts ( "\nSuccessfully connected to Rabbit MQ server! Ready for messages..." ); run ( conn, log_fd , result_routing_key ); close ( log_fd ); lcfg_delete ( cfg ); die_on_amqp_error ( amqp_channel_close ( conn, 1, AMQP_REPLY_SUCCESS ), "Closing channel" ); die_on_amqp_error ( amqp_connection_close ( conn, AMQP_REPLY_SUCCESS ), "Closing connection" ); die_on_error ( amqp_destroy_connection ( conn ), "Ending connection" ); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/murano-agent.conf.example0000664000175000017500000000032000000000000024731 0ustar00zuulzuul00000000000000RABBITMQ_HOST = "localhost" RABBITMQ_PORT = "5672" RABBITMQ_USERNAME = "guest" RABBITMQ_PASSWORD = "guest" RABBITMQ_VHOST = "/" RABBITMQ_INPUT_QUEUE = "test queue" RABBITMQ_RESULT_ROUTING_KEY = "result queue"././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/producer.c0000664000175000017500000001007700000000000022034 0ustar00zuulzuul00000000000000 #include #include #include #include #include #include #include #include "utils.h" #define SUMMARY_EVERY_US 1000000 static void send_batch ( amqp_connection_state_t conn, char const *queue_name, int rate_limit, int message_count ) { uint64_t start_time = now_microseconds(); int i; int sent = 0; int previous_sent = 0; uint64_t previous_report_time = start_time; uint64_t next_summary_time = start_time + SUMMARY_EVERY_US; const char *message = "Hello from the producer!"; amqp_bytes_t message_bytes; message_bytes.len = strlen ( message ); message_bytes.bytes = ( void * ) message; for ( i = 0; i < message_count; i++ ) { uint64_t now = now_microseconds(); amqp_basic_properties_t props; props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_MESSAGE_ID_FLAG; props.message_id = amqp_cstring_bytes( " msg_id " ); props.content_type = amqp_cstring_bytes ( "text/json" ); props.delivery_mode = 2; /* persistent delivery mode */ die_on_error ( amqp_basic_publish ( conn, 1, amqp_cstring_bytes ( "" ), amqp_cstring_bytes ( queue_name ), 0, 0, &props, message_bytes ), "Publishing" ); sent++; if ( now > next_summary_time ) { int countOverInterval = sent - previous_sent; double intervalRate = countOverInterval / ( ( now - previous_report_time ) / 1000000.0 ); printf ( "%d ms: Sent %d - %d since last report (%d Hz)\n", ( int ) ( now - start_time ) / 1000, sent, countOverInterval, ( int ) intervalRate ); previous_sent = sent; previous_report_time = now; next_summary_time += SUMMARY_EVERY_US; } while ( ( ( i * 1000000.0 ) / ( now - start_time ) ) > rate_limit ) { microsleep ( 2000 ); now = now_microseconds(); } } { uint64_t stop_time = now_microseconds(); int total_delta = stop_time - start_time; printf ( "PRODUCER - Message count: %d\n", message_count ); printf ( "Total time, milliseconds: %d\n", total_delta / 1000 ); printf ( "Overall messages-per-second: %g\n", ( message_count / ( total_delta / 1000000.0 ) ) ); } } int main ( int argc, char const *const *argv ) { char const *hostname; int port, status; int rate_limit; int message_count; amqp_socket_t *socket = NULL; amqp_connection_state_t conn; if ( argc < 5 ) { fprintf ( stderr, "Usage: producer host port rate_limit message_count\n" ); return 1; } hostname = argv[1]; port = atoi ( argv[2] ); rate_limit = atoi ( argv[3] ); message_count = atoi ( argv[4] ); conn = amqp_new_connection(); socket = amqp_tcp_socket_new ( conn ); if ( !socket ) { die ( "creating TCP socket" ); } status = amqp_socket_open ( socket, hostname, port ); if ( status ) { die ( "opening TCP socket" ); } die_on_amqp_error ( amqp_login ( conn, "/", 0, 131072, 0, AMQP_SASL_METHOD_PLAIN, "guest", "guest" ), "Logging in" ); amqp_channel_open ( conn, 1 ); die_on_amqp_error ( amqp_get_rpc_reply ( conn ), "Opening channel" ); send_batch ( conn, "test queue", rate_limit, message_count ); die_on_amqp_error ( amqp_channel_close ( conn, 1, AMQP_REPLY_SUCCESS ), "Closing channel" ); die_on_amqp_error ( amqp_connection_close ( conn, AMQP_REPLY_SUCCESS ), "Closing connection" ); die_on_error ( amqp_destroy_connection ( conn ), "Ending connection" ); return 0; } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/utils.c0000664000175000017500000001045300000000000021347 0ustar00zuulzuul00000000000000#include #include #include #include #include #include #include #include #include "utils.h" /* For usleep */ /* #define _BSD_SOURCE */ #include #include #include uint64_t now_microseconds ( void ) { struct timeval tv; gettimeofday ( &tv, NULL ); return ( uint64_t ) tv.tv_sec * 1000000 + ( uint64_t ) tv.tv_usec; } void microsleep ( int usec ) { usleep ( usec ); } void die ( const char *fmt, ... ) { va_list ap; va_start ( ap, fmt ); vfprintf ( stderr, fmt, ap ); va_end ( ap ); fprintf ( stderr, "\n" ); exit ( 1 ); } void die_on_error ( int x, char const *context ) { if ( x < 0 ) { fprintf ( stderr, "%s: %s\n", context, amqp_error_string2 ( x ) ); exit ( 1 ); } } void die_on_amqp_error ( amqp_rpc_reply_t x, char const *context ) { switch ( x.reply_type ) { case AMQP_RESPONSE_NORMAL: return; case AMQP_RESPONSE_NONE: fprintf ( stderr, "%s: missing RPC reply type!\n", context ); break; case AMQP_RESPONSE_LIBRARY_EXCEPTION: fprintf ( stderr, "%s: %s\n", context, amqp_error_string2 ( x.library_error ) ); break; case AMQP_RESPONSE_SERVER_EXCEPTION: switch ( x.reply.id ) { case AMQP_CONNECTION_CLOSE_METHOD: { amqp_connection_close_t *m = ( amqp_connection_close_t * ) x.reply.decoded; fprintf ( stderr, "%s: server connection error %d, message: %.*s\n", context, m->reply_code, ( int ) m->reply_text.len, ( char * ) m->reply_text.bytes ); break; } case AMQP_CHANNEL_CLOSE_METHOD: { amqp_channel_close_t *m = ( amqp_channel_close_t * ) x.reply.decoded; fprintf ( stderr, "%s: server channel error %d, message: %.*s\n", context, m->reply_code, ( int ) m->reply_text.len, ( char * ) m->reply_text.bytes ); break; } default: fprintf ( stderr, "%s: unknown server error, method id 0x%08X\n", context, x.reply.id ); break; } break; } exit ( 1 ); } static void dump_row ( long count, int numinrow, int *chs ) { int i; printf ( "%08lX:", count - numinrow ); if ( numinrow > 0 ) { for ( i = 0; i < numinrow; i++ ) { if ( i == 8 ) { printf ( " :" ); } printf ( " %02X", chs[i] ); } for ( i = numinrow; i < 16; i++ ) { if ( i == 8 ) { printf ( " :" ); } printf ( " " ); } printf ( " " ); for ( i = 0; i < numinrow; i++ ) { if ( isprint ( chs[i] ) ) { printf ( "%c", chs[i] ); } else { printf ( "." ); } } } printf ( "\n" ); } static int rows_eq ( int *a, int *b ) { int i; for ( i=0; i<16; i++ ) if ( a[i] != b[i] ) { return 0; } return 1; } void amqp_dump ( void const *buffer, size_t len ) { unsigned char *buf = ( unsigned char * ) buffer; long count = 0; int numinrow = 0; int chs[16]; int oldchs[16] = {0}; int showed_dots = 0; size_t i; for ( i = 0; i < len; i++ ) { int ch = buf[i]; if ( numinrow == 16 ) { int i; if ( rows_eq ( oldchs, chs ) ) { if ( !showed_dots ) { showed_dots = 1; printf ( " .. .. .. .. .. .. .. .. : .. .. .. .. .. .. .. ..\n" ); } } else { showed_dots = 0; dump_row ( count, numinrow, chs ); } for ( i=0; i<16; i++ ) { oldchs[i] = chs[i]; } numinrow = 0; } count++; chs[numinrow++] = ch; } dump_row ( count, numinrow, chs ); if ( numinrow != 0 ) { printf ( "%08lX:\n", count ); } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/c-demo-agent/utils.h0000664000175000017500000000052600000000000021354 0ustar00zuulzuul00000000000000#ifndef agent_utils_h #define agent_utils_h void die(const char *fmt, ...); extern void die_on_error(int x, char const *context); extern void die_on_amqp_error(amqp_rpc_reply_t x, char const *context); extern void amqp_dump(void const *buffer, size_t len); extern uint64_t now_microseconds(void); extern void microsleep(int usec); #endif ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2288828 murano-agent-9.0.0/contrib/elements/0000775000175000017500000000000000000000000017414 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1648641201.220883 murano-agent-9.0.0/contrib/elements/murano-agent/0000775000175000017500000000000000000000000022011 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2288828 murano-agent-9.0.0/contrib/elements/murano-agent/install.d/0000775000175000017500000000000000000000000023701 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/murano-agent/install.d/74-murano-agent0000775000175000017500000000302400000000000026453 0ustar00zuulzuul00000000000000#!/bin/bash set -eu install-packages git-core wget make gcc python-pip python-dev python-setuptools puppet if test -f /etc/redhat-release then rpm -Uvh https://packages.chef.io/stable/el/7/chef-12.9.41-1.el7.x86_64.rpm else install-packages chef fi name=murano-agent svc_root=${DIB_MURANO_AGENT_SVC_ROOT:-/opt/stack/$name} repo=${DIB_MURANO_AGENT_REPO:-https://opendev.org/openstack/murano-agent.git} branch=${DIB_MURANO_AGENT_BRANCH:-master} ref=${DIB_MURANO_AGENT_REF:-''} # clone murano-agent source code into /opt/stack/murano-agent mkdir -p $svc_root git clone --depth=1 -b $branch $repo $svc_root if [ -n "$ref" ]; then pushd $svc_root git fetch $repo $ref && git checkout FETCH_HEAD popd fi # install murano-agent to default location using pip # FIXME(starodubcevna): probably pip is not the best case for this. I suggest to # switch to package when they will be available to all supported distros. pip install $svc_root # setup config file at /etc/murano/agent.conf mkdir -p /etc/murano PATH="/usr/local/bin:/usr/bin:$PATH" pushd ${svc_root} oslo-config-generator --config-file ${svc_root}/etc/oslo-config-generator/muranoagent.conf popd cp ${svc_root}/etc/muranoagent/muranoagent.conf.sample /etc/murano/agent.conf.sample # install upstart script for murano-agent if [ -d "/etc/init/" ]; then install -D -g root -o root -m 0755 $(dirname $0)/murano-agent.conf /etc/init/ fi if [ -d "/etc/systemd/system/" ]; then install -D -g root -o root -m 0755 $(dirname $0)/murano-agent.service /etc/systemd/system/ fi ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/murano-agent/install.d/murano-agent.conf0000664000175000017500000000063600000000000027152 0ustar00zuulzuul00000000000000start on runlevel [2345] stop on runlevel [016] respawn # the default post-start of 1 second sleep delays respawning enough to # not hit the default of 10 times in 5 seconds. Make it 2 times in 5s. respawn limit 2 5 # We're logging to syslog console none exec start-stop-daemon --start -c root --exec /usr/local/bin/muranoagent -- --config-dir /etc/murano 2>&1 | logger -t murano-agent post-start exec sleep 1 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/murano-agent/install.d/murano-agent.service0000664000175000017500000000027000000000000027657 0ustar00zuulzuul00000000000000[Unit] Description=OpenStack Murano Agent [Service] Type=simple ExecStart=/usr/local/bin/muranoagent --config-dir /etc/murano Restart=on-failure [Install] WantedBy=multi-user.target ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2288828 murano-agent-9.0.0/contrib/elements/murano-agent-debian/0000775000175000017500000000000000000000000023231 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/murano-agent-debian/element-deps0000664000175000017500000000004400000000000025534 0ustar00zuulzuul00000000000000cloud-init-datasources murano-agent ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2288828 murano-agent-9.0.0/contrib/elements/murano-agent-debian/install.d/0000775000175000017500000000000000000000000025121 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/murano-agent-debian/install.d/11-murano-agent-debian0000775000175000017500000000044600000000000031107 0ustar00zuulzuul00000000000000#!/bin/bash set -eu set -o pipefail # Fix problem with default hostname rm -rf /etc/cloud/cloud.cfg.d/01_hostname.cfg # Fix problem with locale generation sed -e '/# en_US.UTF-8/ s/^# //' -i /etc/locale.gen locale-gen sed -e 's/exit 0/service murano-agent start\nexit 0/g' -i /etc/rc.local ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/murano-agent-debian/package-installs.yaml0000664000175000017500000000065100000000000027341 0ustar00zuulzuul00000000000000inetutils-ping: net-tools: vim: isc-dhcp-client: git-core: wget: make: gcc: python-pip: dib_python_version: 2 python3-pip: dib_python_version: 3 python-dev: dib_python_version: 2 python3-dev: dib_python_version: 3 python-setuptools: dib_python_version: 2 python3-setuptools: dib_python_version: 3 python-virtualenv: dib_python_version: 2 python3-virtualenv: dib_python_version: 3 iptables: virtualenvwrapper: ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/elements/readme.rst0000664000175000017500000000205500000000000021405 0ustar00zuulzuul00000000000000Murano Agent Elements ===================== This folder contains necessary DIB elements to build Murano Agent image. Prerequisites ------------- 1. Install diskimage-builder .. sourcecode:: bash sudo pip install diskimage-builder 2. Install qemu-uils and kpartx On Ubuntu, Debian: .. sourcecode:: bash sudo apt-get install qemu-utils kpartx On Centos, Fedora: .. sourcecode:: bash sudo yum install qemu-utils kpartx Image building -------------- To build Ubuntu-based image .. sourcecode:: bash sudo ELEMENTS_PATH=${murano_agent_root}/contrib/elements \ DIB_CLOUD_INIT_DATASOURCES="Ec2, ConfigDrive, OpenStack" disk-image-create \ vm ubuntu murano-agent -o ubuntu14.04-x64-agent To build Debian-based image .. sourcecode:: bash sudo ELEMENTS_PATH=${murano_agent_root}/contrib/elements DIB_RELEASE=jessie \ DIB_CLOUD_INIT_DATASOURCES="Ec2, ConfigDrive, OpenStack" disk-image-create \ vm debian murano-agent-debian -o debian8-x64-agent Where ${murano_agent_root} is a path to murano-agent files. ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2288828 murano-agent-9.0.0/contrib/windows-agent/0000775000175000017500000000000000000000000020366 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2328827 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/0000775000175000017500000000000000000000000025013 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/App.config0000664000175000017500000000026600000000000026726 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/ExecutionPlanGenerator.csproj0000664000175000017500000000522000000000000032661 0ustar00zuulzuul00000000000000 Debug AnyCPU {501BE151-4B8C-4355-88DC-3AEF1921B2D7} Exe Properties Mirantis.Murano ExecutionPlanGenerator v4.5 512 AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 AnyCPU pdbonly true bin\Release\ TRACE prompt 4 ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/Program.cs0000664000175000017500000000746000000000000026760 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using Newtonsoft.Json; namespace Mirantis.Murano { internal class Command { public string Name { get; set; } public Dictionary Arguments { get; set; } } internal class ExecutionPlan { public List Scripts { get; set; } public List Commands { get; set; } public int RebootOnCompletion { get; set; } } static class Program { public static void Main(string[] args) { if (args.Length < 1 || args.Length > 2) { Console.WriteLine("Usage: ExecutionPlanGenerator inputfile [outputfile]"); return; } var outFile = args.Length == 2 ? args[1] : null; var plan = new ExecutionPlan { Scripts = new List(), Commands = new List() }; var lines = File.ReadAllLines(args[0]); foreach (var statement in lines .Select(t => t.Split(new[] { ' ', '\t' }, 2)) .Where(t => t.Length == 2) .Select(t => new Tuple(t[0].Trim().ToLower(), t[1].Trim()))) { switch (statement.Item1) { case "include": Include(statement.Item2, plan, args[0]); break; case "call": Call(statement.Item2, plan); break; case "reboot": plan.RebootOnCompletion = int.Parse(statement.Item2); break; case "out": if (args.Length < 2) { var path = statement.Item2; if (!Path.IsPathRooted(path)) { path = Path.Combine(Path.GetDirectoryName(args[0]), path); } outFile = path; } break; } } var data = JsonConvert.SerializeObject(plan, Formatting.Indented); if (outFile == null) { Console.WriteLine(data); } else { File.WriteAllText(outFile, data); } } private static void Call(string line, ExecutionPlan plan) { var parts = line.Split(new[] { ' ', '\t'}, 2); var command = new Command() { Name = parts[0].Trim(), Arguments = new Dictionary() }; if (parts.Length == 2) { foreach (var x in parts[1] .Split(',') .Select(t => t.Split('=')) .Where(t => t.Length == 2) .Select(t => new KeyValuePair(t[0].Trim(), t[1].Trim()))) { object value = null; long num; bool boolean; if (x.Value.StartsWith("\"")) { value = x.Value.Substring(1, x.Value.Length - 2); } else if (long.TryParse(x.Value, out num)) { value = num; } else if (bool.TryParse(x.Value, out boolean)) { value = boolean; } else { continue; } command.Arguments.Add(x.Key, value); } } plan.Commands.Add(command); } private static void Include(string file, ExecutionPlan plan, string dslPath) { var path = file; if (!Path.IsPathRooted(file)) { path = Path.Combine(Path.GetDirectoryName(dslPath), path); } var text = File.ReadAllText(path, Encoding.UTF8); plan.Scripts.Add(Convert.ToBase64String(Encoding.UTF8.GetBytes(text))); } } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2328827 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/Properties/0000775000175000017500000000000000000000000027147 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/Properties/AssemblyInfo.cs0000664000175000017500000000423400000000000032074 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("ConsoleApplication1")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("ConsoleApplication1")] [assembly: AssemblyCopyright("Copyright © 2013")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("9aab688a-ce5f-402e-8891-2d7b4ae85ea3")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/ExecutionPlanGenerator/packages.config0000664000175000017500000000021400000000000027755 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/README.rst0000664000175000017500000000216600000000000022062 0ustar00zuulzuul00000000000000Murano Windows Agent ==================== Murano Windows Agent is an initial version of Murano Agent. Currently, it's outdated and not supported. The main difference with the new Python agent is support of running PowerShell. After this support will be added to Python Agent, Windows Agent will be dropped. How to build ============ Build using Visual Studio ------------------------- 1. Launch Visual Studio #. Ensure that you have latest ``NuGet`` extension installed (shipped with recent versions of VS) #. Open ``WindowsAgent.sln`` #. Select target configuration (Release or Debug) using drop-down found in VS toolbar #. Build the Solution (Build menu -> Build Solution). Build from command line ----------------------- 1. CD to where ``WindowsAgent.sln`` is located #. Download nuget.exe from https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to current directory. #. Run ``nuget.exe restore`` #. Build the solution using msbuild: ``C:\\Windows\\Microsoft.NET\\Framework64\\v4.0.30319\\MSBuild.exe /p:Configuration=Release`` The exact path to msbuild may differ on your system and .NET version installed.././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2328827 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/0000775000175000017500000000000000000000000022777 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/App.config0000664000175000017500000000204600000000000024710 0ustar00zuulzuul00000000000000
././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/ExecutionPlan.cs0000664000175000017500000000230000000000000026077 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Collections.Generic; namespace Mirantis.Murano.WindowsAgent { internal class ExecutionPlan { public class Command { public string Name { get; set; } public Dictionary Arguments { get; set; } } public string[] Scripts { get; set; } public LinkedList Commands { get; set; } public int RebootOnCompletion { get; set; } public long Stamp { get; set; } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/Message.cs0000664000175000017500000000217400000000000024716 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; namespace Mirantis.Murano.WindowsAgent { internal class Message : IDisposable { private readonly Action ackFunc; public Message(Action ackFunc) { this.ackFunc = ackFunc; } public Message() { } public string Body { get; set; } public string Id { get; set; } public void Dispose() { ackFunc(); } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/MessageSource.cs0000664000175000017500000001263700000000000026104 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.Configuration; using System.Net.Security; using System.Security.Authentication; using System.Text; using NLog; using RabbitMQ.Client; namespace Mirantis.Murano.WindowsAgent { internal class MessageSource : IDisposable { private static readonly Logger log = LogManager.GetCurrentClassLogger(); private static readonly ConnectionFactory connectionFactory; private static readonly string queueName; private IConnection currentConnecton; private readonly SignatureVerifier signatureVerifier; static MessageSource() { var ssl = new SslOption { Enabled = bool.Parse(ConfigurationManager.AppSettings["rabbitmq.ssl"] ?? "false"), Version = SslProtocols.Default, AcceptablePolicyErrors = bool.Parse(ConfigurationManager.AppSettings["rabbitmq.allowInvalidCA"] ?? "true") ? SslPolicyErrors.RemoteCertificateChainErrors : SslPolicyErrors.None }; var sslServerName = ConfigurationManager.AppSettings["rabbitmq.sslServerName"] ?? ""; ssl.ServerName = sslServerName; if (String.IsNullOrWhiteSpace(sslServerName)) { ssl.AcceptablePolicyErrors |= SslPolicyErrors.RemoteCertificateNameMismatch; } connectionFactory = new ConnectionFactory { HostName = ConfigurationManager.AppSettings["rabbitmq.host"] ?? "localhost", UserName = ConfigurationManager.AppSettings["rabbitmq.user"] ?? "guest", Password = ConfigurationManager.AppSettings["rabbitmq.password"] ??"guest", Protocol = Protocols.DefaultProtocol, VirtualHost = ConfigurationManager.AppSettings["rabbitmq.vhost"] ?? "/", Port = int.Parse(ConfigurationManager.AppSettings["rabbitmq.port"] ?? "5672"), RequestedHeartbeat = 10, Ssl = ssl }; queueName = ConfigurationManager.AppSettings["rabbitmq.inputQueue"]; } public MessageSource() { this.signatureVerifier = new SignatureVerifier(Encoding.ASCII.GetBytes(queueName)); } public Message GetMessage() { try { IConnection connection; lock (this) { connection = this.currentConnecton = this.currentConnecton ?? connectionFactory.CreateConnection(); } var session = connection.CreateModel(); session.BasicQos(0, 1, false); var consumer = new QueueingBasicConsumer(session); var consumeTag = session.BasicConsume(queueName, false, consumer); while (true) { var e = consumer.Queue.Dequeue(); Action ackFunc = delegate { session.BasicAck(e.DeliveryTag, false); session.BasicCancel(consumeTag); session.Close(); }; byte[] signature = null; if (e.BasicProperties.Headers.ContainsKey("signature")) { signature = (byte[]) e.BasicProperties.Headers["signature"]; } if (this.signatureVerifier.Verify(e.Body, signature)) { return new Message(ackFunc) { Body = Encoding.UTF8.GetString(e.Body), Id = e.BasicProperties.MessageId, }; } log.Warn("Dropping message with invalid/missing signature"); session.BasicReject(e.DeliveryTag, false); } } catch (Exception) { if (this.currentConnecton == null) return null; Dispose(); throw; } } public void SendResult(Message message) { var exchangeName = ConfigurationManager.AppSettings["rabbitmq.resultExchange"] ?? ""; var resultRoutingKey = ConfigurationManager.AppSettings["rabbitmq.resultRoutingKey"] ?? "-execution-results"; bool durable = bool.Parse(ConfigurationManager.AppSettings["rabbitmq.durableMessages"] ?? "true"); try { IConnection connection; lock (this) { connection = this.currentConnecton = this.currentConnecton ?? connectionFactory.CreateConnection(); } var session = connection.CreateModel(); var basicProperties = session.CreateBasicProperties(); basicProperties.Persistent = durable; basicProperties.MessageId = message.Id; basicProperties.ContentType = "application/json"; session.BasicPublish(exchangeName, resultRoutingKey, basicProperties, Encoding.UTF8.GetBytes(message.Body)); session.Close(); } catch (Exception) { Dispose(); throw; } } public void Dispose() { lock (this) { try { var connection = this.currentConnecton; this.currentConnecton = null; connection.Close(); } catch { } } } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/PlanExecutor.cs0000664000175000017500000001775200000000000025753 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Management.Automation; using System.Management.Automation.Runspaces; using System.Text; using Newtonsoft.Json.Linq; using NLog; using Newtonsoft.Json; namespace Mirantis.Murano.WindowsAgent { internal class PlanExecutor { private static readonly Logger log = LogManager.GetCurrentClassLogger(); private long lastStamp = -1; class ExecutionResult { public bool IsException { get; set; } public object Result { get; set; } } private readonly string baseDir; public PlanExecutor(string baseDir) { this.baseDir = baseDir; } public bool RebootNeeded { get; set; } public void Execute(string path) { RebootNeeded = false; var resultPath = path + ".result"; var tmpResultPath = resultPath + ".tmp"; Runspace runSpace = null; try { var plan = JsonConvert.DeserializeObject(File.ReadAllText(path)); List currentResults; try { currentResults = File.Exists(tmpResultPath) ? JsonConvert.DeserializeObject>(File.ReadAllText(tmpResultPath)) : new List(); } catch(Exception exception) { log.Warn(exception, "Cannot deserialize previous execution result"); currentResults = new List(); } var lastStamp = GetLastStamp(); if (plan.Stamp > 0 && plan.Stamp <= lastStamp) { log.Warn("Dropping old/duplicate plan"); return; } runSpace = RunspaceFactory.CreateRunspace(); runSpace.Open(); var runSpaceInvoker = new RunspaceInvoke(runSpace); runSpaceInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); if (plan.Scripts != null) { var index = 0; foreach (var script in plan.Scripts) { runSpaceInvoker.Invoke(Encoding.UTF8.GetString(Convert.FromBase64String(script))); log.Debug("Loaded script #{0}", ++index); } } while (plan.Commands != null && plan.Commands.Any()) { var command = plan.Commands.First(); log.Debug("Preparing to execute command {0}", command.Name); var pipeline = runSpace.CreatePipeline(); if (command.Name != null) { var psCommand = new Command(command.Name); if (command.Arguments != null) { foreach (var kvp in command.Arguments) { var value = ConvertArgument(kvp.Value); psCommand.Parameters.Add(kvp.Key, value); } } log.Info("Executing {0} {1}", command.Name, string.Join(" ", (command.Arguments ?? new Dictionary()).Select( t => string.Format("{0}={1}", t.Key, t.Value?.ToString() ?? "null")))); pipeline.Commands.Add(psCommand); } try { var result = pipeline.Invoke(); log.Debug("Command {0} executed", command.Name); if (result != null) { currentResults.Add(new ExecutionResult { IsException = false, Result = result.Where(obj => obj != null).Select(SerializePsObject).ToList() }); } } catch (Exception exception) { object additionInfo = null; var apse = exception as ActionPreferenceStopException; if (apse?.ErrorRecord != null) { additionInfo = new { ScriptStackTrace = apse.ErrorRecord.ScriptStackTrace, PositionMessage = apse.ErrorRecord.InvocationInfo.PositionMessage }; exception = apse.ErrorRecord.Exception; } log.Warn(exception, "Exception while executing command " + command.Name); currentResults.Add(new ExecutionResult { IsException = true, Result = new[] { exception.GetType().FullName, exception.Message, command.Name, additionInfo } }); break; } finally { plan.Commands.RemoveFirst(); File.WriteAllText(path, JsonConvert.SerializeObject(plan)); File.WriteAllText(tmpResultPath, JsonConvert.SerializeObject(currentResults)); } } runSpace.Close(); if (plan.Stamp > 0) { SetLastStamp(plan.Stamp); } var executionResult = JsonConvert.SerializeObject(new ExecutionResult { IsException = false, Result = currentResults }, Formatting.Indented); if (plan.RebootOnCompletion > 0) { if (plan.RebootOnCompletion == 1) { RebootNeeded = !currentResults.Any(t => t.IsException); } else { RebootNeeded = true; } } File.Delete(tmpResultPath); File.WriteAllText(resultPath, executionResult); } catch (Exception exception) { log.Warn(exception, "Exception while processing execution plan"); File.WriteAllText(resultPath, JsonConvert.SerializeObject(new ExecutionResult { IsException = true, Result = exception.Message }, Formatting.Indented)); } finally { if (runSpace != null) { try { runSpace.Close(); } catch {} } log.Debug("Finished processing of execution plan"); } } private static object ConvertArgument(object arg) { switch (arg) { case JArray array: return array.Select(ConvertArgument).ToArray(); case JValue value: return value.Value; case JObject dict: var result = new Hashtable(); foreach (var item in dict) { result.Add(item.Key, ConvertArgument(item.Value)); } return result; } return arg; } private static object SerializePsObject(PSObject obj) { if (obj.BaseObject is PSCustomObject) { var result = new Dictionary(); foreach (var property in obj.Properties.Where(p => p.IsGettable)) { try { result[property.Name] = property.Value.ToString(); } catch { } } return result; } if (obj.BaseObject is IEnumerable objects) { return objects.Select(SerializePsObject).ToArray(); } return obj.BaseObject; } private long GetLastStamp() { if (this.lastStamp >= 0) { return this.lastStamp; } var path = Path.Combine(this.baseDir, "stamp.txt"); if (File.Exists(path)) { try { var stampData = File.ReadAllText(path); this.lastStamp = long.Parse(stampData); } catch (Exception e) { this.lastStamp = 0; } } else { this.lastStamp = 0; } return this.lastStamp; } private void SetLastStamp(long value) { var path = Path.Combine(this.baseDir, "stamp.txt"); try { File.WriteAllText(path, value.ToString()); } catch (Exception e) { log.Error(e, "Cannot persist last stamp"); throw; } finally { this.lastStamp = value; } } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/Program.cs0000664000175000017500000001075600000000000024746 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Management.Automation; using System.Security.AccessControl; using System.Security.Principal; using System.Threading; using NLog; namespace Mirantis.Murano.WindowsAgent { [DisplayName("Murano Agent")] public sealed class Program : WindowsService { private static readonly Logger log = LogManager.GetCurrentClassLogger(); private volatile bool stop; private Thread thread; private MessageSource messageSource; private int delayFactor = 1; private string plansDir; public static void Main(string[] args) { Start(new Program(), args); } protected override void OnStart(string[] args) { base.OnStart(args); log.Info("Version 0.6"); this.messageSource = new MessageSource(); var basePath = Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName); this.plansDir = Path.Combine(basePath, "plans"); if (!Directory.Exists(plansDir)) { Directory.CreateDirectory(plansDir); } this.thread = new Thread(Loop); this.thread.Start(); } private void Loop() { const string unknownName = "unknown"; var executor = new PlanExecutor(this.plansDir); while (!stop) { try { foreach (var file in Directory.GetFiles(this.plansDir, "*.json.result") .Where(file => !File.Exists(Path.Combine(this.plansDir, Path.GetFileNameWithoutExtension(file))))) { var id = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(file)); if (id.Equals(unknownName, StringComparison.InvariantCultureIgnoreCase)) { id = ""; } var result = File.ReadAllText(file); log.Info("Sending results for {0}", id); messageSource.SendResult(new Message { Body = result, Id = id }); File.Delete(file); } var path = Directory.EnumerateFiles(this.plansDir, "*.json").FirstOrDefault(); if (path == null) { using (var message = messageSource.GetMessage()) { if (message == null) { return; } var id = message.Id; if (string.IsNullOrEmpty(id)) { id = unknownName; } path = Path.Combine(this.plansDir, string.Format("{0}.json", id)); File.WriteAllText(path, message.Body); log.Info("Received new execution plan {0}", id); } } else { var id = Path.GetFileNameWithoutExtension(path); log.Info("Executing exising plan {0}", id); } executor.Execute(path); File.Delete(path); delayFactor = 1; if (stop) break; if (executor.RebootNeeded) { Reboot(); } } catch (Exception exception) { WaitOnException(exception); } } } private void Reboot() { log.Info("Going for reboot!!"); LogManager.Flush(); try { PowerShell.Create().AddCommand("Restart-Computer").AddParameter("Force").Invoke(); } catch (Exception exception) { log.Fatal(exception, "Reboot exception"); } finally { log.Info("Waiting for reboot"); for (var i = 0; i < 10 * 60 * 5 && !stop; i++) { Thread.Sleep(100); } log.Info("Done waiting for reboot"); } } private void WaitOnException(Exception exception) { if (stop) return; log.Warn(exception, "Exception in main loop"); var i = 0; while (!stop && i < 10 * (delayFactor * delayFactor)) { Thread.Sleep(100); i++; } delayFactor = Math.Min(delayFactor + 1, 6); } protected override void OnStop() { stop = true; this.messageSource.Dispose(); base.OnStop(); } } } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2328827 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/Properties/0000775000175000017500000000000000000000000025133 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/Properties/AssemblyInfo.cs0000664000175000017500000000421600000000000030060 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("WindowsAgent")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("WindowsAgent")] [assembly: AssemblyCopyright("Copyright © 2013")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] // Setting ComVisible to false makes the types in this assembly not visible // to COM components. If you need to access a type in this assembly from // COM, set the ComVisible attribute to true on that type. [assembly: ComVisible(false)] // The following GUID is for the ID of the typelib if this project is exposed to COM [assembly: Guid("9591bf2c-f38b-47e0-a39d-ea9849356371")] // Version information for an assembly consists of the following four values: // // Major Version // Minor Version // Build Number // Revision // // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] [assembly: AssemblyFileVersion("1.0.0.0")] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/SampleExecutionPlan.json0000664000175000017500000000166300000000000027620 0ustar00zuulzuul00000000000000{ "Scripts": [ "ZnVuY3Rpb24gdDMgeyAxMjsgcmV0dXJuICJ0ZXN0IiB9", "ZnVuY3Rpb24gTmV3LVBlcnNvbigpDQp7DQogIHBhcmFtICgkRmlyc3ROYW1lLCAkTGFzdE5hbWUsICRQaG9uZSkNCg0KICAkcGVyc29uID0gbmV3LW9iamVjdCBQU09iamVjdA0KDQogICRwZXJzb24gfCBhZGQtbWVtYmVyIC10eXBlIE5vdGVQcm9wZXJ0eSAtTmFtZSBGaXJzdCAtVmFsdWUgJEZpcnN0TmFtZQ0KICAkcGVyc29uIHwgYWRkLW1lbWJlciAtdHlwZSBOb3RlUHJvcGVydHkgLU5hbWUgTGFzdCAtVmFsdWUgJExhc3ROYW1lDQogICRwZXJzb24gfCBhZGQtbWVtYmVyIC10eXBlIE5vdGVQcm9wZXJ0eSAtTmFtZSBQaG9uZSAtVmFsdWUgJFBob25lDQoNCiAgcmV0dXJuICRwZXJzb24NCn0=", "ZnVuY3Rpb24gVGVzdFRocm93KCkNCnsNCglUaHJvdyBbc3lzdGVtLkluZGV4T3V0T2ZSYW5nZUV4Y2VwdGlvbl0gDQp9" ], "Commands" : [ { "Name": "New-Person", "Arguments" : { "FirstName": "MyFirstName", "LastName": "MyLastName", "Phone": "123-456" } }, { "Name": "t3", "Arguments" : { } }, { "Name": "Get-Date", }, { "Name": "TestThrow", } ], "RebootOnCompletion": 0 }././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/ServiceManager.cs0000664000175000017500000000765700000000000026240 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.Configuration.Install; using System.Reflection; using System.ServiceProcess; using NLog; namespace Mirantis.Murano.WindowsAgent { public class ServiceManager { private readonly string serviceName; public ServiceManager(string serviceName) { this.serviceName = serviceName; } private static readonly Logger log = LogManager.GetCurrentClassLogger(); public bool Restart(string[] args, TimeSpan timeout) { var service = new ServiceController(serviceName); try { var millisec1 = TimeSpan.FromMilliseconds(Environment.TickCount); service.Stop(); service.WaitForStatus(ServiceControllerStatus.Stopped, timeout); log.Info("Service is stopped"); // count the rest of the timeout var millisec2 = TimeSpan.FromMilliseconds(Environment.TickCount); timeout = timeout - (millisec2 - millisec1); service.Start(args); service.WaitForStatus(ServiceControllerStatus.Running, timeout); log.Info("Service has started"); return true; } catch (Exception ex) { log.Error(ex, "Cannot restart service " + serviceName); return false; } } public bool Stop(TimeSpan timeout) { var service = new ServiceController(serviceName); try { service.Stop(); service.WaitForStatus(ServiceControllerStatus.Stopped, timeout); return true; } catch (Exception ex) { log.Error(ex, "Cannot stop service " + serviceName); return false; } } public bool Start(string[] args, TimeSpan timeout) { var service = new ServiceController(serviceName); try { service.Start(args); service.WaitForStatus(ServiceControllerStatus.Running, timeout); return true; } catch (Exception ex) { log.Error(ex, "Cannot start service " + serviceName); return false; } } public bool Install() { try { ManagedInstallerClass.InstallHelper( new[] { Assembly.GetEntryAssembly().Location }); } catch(Exception ex) { log.Error(ex, "Cannot install service " + serviceName); return false; } return true; } public bool Uninstall() { try { ManagedInstallerClass.InstallHelper( new[] { "/u", Assembly.GetEntryAssembly().Location }); } catch (Exception ex) { log.Error(ex, "Cannot uninstall service " + serviceName); return false; } return true; } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/SignatureVerifier.cs0000664000175000017500000000411500000000000026764 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.Configuration; using System.IO; using Org.BouncyCastle.Crypto; using Org.BouncyCastle.Crypto.Parameters; using Org.BouncyCastle.OpenSsl; using Org.BouncyCastle.Security; namespace Mirantis.Murano.WindowsAgent { internal class SignatureVerifier { private readonly ISigner signer; private readonly byte[] salt; public SignatureVerifier(byte[] salt) { var keyStr = ConfigurationManager.AppSettings["engine.key"]; if (string.IsNullOrEmpty(keyStr)) return; var reader = new StringReader(keyStr); var key = (RsaKeyParameters) new PemReader(reader).ReadObject(); this.signer = SignerUtilities.GetSigner("SHA256withRSA"); this.signer.Init(false, key); this.salt = salt; } public bool Verify(byte[] data, byte[] signature) { if (this.signer == null) { return true; } if (signature == null) { return false; } this.signer.Reset(); this.signer.BlockUpdate(this.salt, 0, this.salt.Length); this.signer.BlockUpdate(data, 0, data.Length); return this.signer.VerifySignature(signature); } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/WindowsAgent.csproj0000664000175000017500000001077200000000000026641 0ustar00zuulzuul00000000000000 Debug AnyCPU {F7E2A8D5-6D24-4651-A4BC-1024D59F4903} Exe Properties Mirantis.Murano.WindowsAgent WindowsAgent v4.5 512 AnyCPU true full false bin\Debug\ DEBUG;TRACE prompt 4 false AnyCPU pdbonly true bin\Release\ TRACE prompt 4 false ..\packages\BouncyCastle.1.8.1\lib\BouncyCastle.Crypto.dll ..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll ..\packages\NLog.4.4.12\lib\net45\NLog.dll ..\packages\RabbitMQ.Client.3.6.9\lib\net45\RabbitMQ.Client.dll False C:\Program Files (x86)\Reference Assemblies\Microsoft\WindowsPowerShell\3.0\System.Management.Automation.dll Component Component Component Designer ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/WindowsService.cs0000664000175000017500000000664600000000000026315 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System; using System.ComponentModel; using System.IO; using System.Linq; using System.Reflection; using System.ServiceProcess; using NLog; namespace Mirantis.Murano.WindowsAgent { public abstract class WindowsService : ServiceBase { private static readonly Logger log = LogManager.GetCurrentClassLogger(); protected static void Start(WindowsService service, string[] arguments) { Directory.SetCurrentDirectory(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location)); if (arguments.Contains("/install", StringComparer.OrdinalIgnoreCase)) { new ServiceManager(service.ServiceName).Install(); } else if (arguments.Contains("/uninstall", StringComparer.OrdinalIgnoreCase)) { new ServiceManager(service.ServiceName).Uninstall(); } else if (arguments.Contains("/start", StringComparer.OrdinalIgnoreCase)) { new ServiceManager(service.ServiceName).Start(Environment.GetCommandLineArgs(), TimeSpan.FromMinutes(1)); } else if (arguments.Contains("/stop", StringComparer.OrdinalIgnoreCase)) { new ServiceManager(service.ServiceName).Stop(TimeSpan.FromMinutes(1)); } else if (arguments.Contains("/restart", StringComparer.OrdinalIgnoreCase)) { new ServiceManager(service.ServiceName).Restart(Environment.GetCommandLineArgs(), TimeSpan.FromMinutes(1)); } else if (!arguments.Contains("/console", StringComparer.OrdinalIgnoreCase)) { Run(service); } else { try { Console.Title = service.ServiceName; service.OnStart(Environment.GetCommandLineArgs()); service.WaitForExitSignal(); } finally { service.OnStop(); service.Dispose(); } } } protected WindowsService() { var displayNameAttribute = this.GetType().GetCustomAttributes(typeof (DisplayNameAttribute), false).Cast(). FirstOrDefault(); if(displayNameAttribute != null) { ServiceName = displayNameAttribute.DisplayName; } } protected virtual void WaitForExitSignal() { Console.WriteLine("Press ESC to exit"); while (Console.ReadKey(true).Key != ConsoleKey.Escape) { } } protected override void OnStart(string[] args) { log.Info("Service {0} started", ServiceName); base.OnStart(args); } protected override void OnStop() { log.Info("Service {0} exited", ServiceName); base.OnStop(); } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/WindowsServiceInstaller.cs0000664000175000017500000000437300000000000030166 0ustar00zuulzuul00000000000000// Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to you under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. using System.ComponentModel; using System.Configuration.Install; using System.Linq; using System.Reflection; using System.ServiceProcess; namespace Mirantis.Murano.WindowsAgent { [RunInstaller(true)] public class WindowsServiceInstaller : Installer { public WindowsServiceInstaller() { var processInstaller = new ServiceProcessInstaller { Account = ServiceAccount.LocalSystem }; foreach (var type in Assembly.GetEntryAssembly().GetExportedTypes().Where(t => t.IsSubclassOf(typeof(ServiceBase)))) { var nameAttribute = type.GetCustomAttributes(typeof (DisplayNameAttribute), false) .Cast().FirstOrDefault(); if(nameAttribute == null) continue; var serviceInstaller = new ServiceInstaller { StartType = ServiceStartMode.Automatic, ServiceName = nameAttribute.DisplayName, DisplayName = nameAttribute.DisplayName }; var descriptionAttribute = type.GetCustomAttributes(typeof(DescriptionAttribute), false) .Cast().FirstOrDefault(); if(descriptionAttribute != null) { serviceInstaller.Description = descriptionAttribute.Description; } Installers.Add(serviceInstaller); } Installers.Add(processInstaller); } } } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent/packages.config0000664000175000017500000000054100000000000025744 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/contrib/windows-agent/WindowsAgent.sln0000664000175000017500000000261400000000000023520 0ustar00zuulzuul00000000000000 Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WindowsAgent", "WindowsAgent\WindowsAgent.csproj", "{F7E2A8D5-6D24-4651-A4BC-1024D59F4903}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ExecutionPlanGenerator", "ExecutionPlanGenerator\ExecutionPlanGenerator.csproj", "{501BE151-4B8C-4355-88DC-3AEF1921B2D7}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Debug|Any CPU.Build.0 = Debug|Any CPU {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Release|Any CPU.ActiveCfg = Release|Any CPU {F7E2A8D5-6D24-4651-A4BC-1024D59F4903}.Release|Any CPU.Build.0 = Release|Any CPU {501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Debug|Any CPU.Build.0 = Debug|Any CPU {501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Release|Any CPU.ActiveCfg = Release|Any CPU {501BE151-4B8C-4355-88DC-3AEF1921B2D7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection EndGlobal ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2328827 murano-agent-9.0.0/doc/0000775000175000017500000000000000000000000014705 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/doc/requirements.txt0000664000175000017500000000025600000000000020174 0ustar00zuulzuul00000000000000sphinx>=2.0.0,!=2.1.0 # BSD openstackdocstheme>=2.2.1 # Apache-2.0 sphinxcontrib-pecanwsme>=0.8.0 # Apache-2.0 sphinxcontrib-httpdomain>=1.3.0 # BSD reno>=3.1.0 # Apache-2.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2328827 murano-agent-9.0.0/doc/source/0000775000175000017500000000000000000000000016205 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/doc/source/conf.py0000664000175000017500000000470200000000000017507 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys sys.path.insert(0, os.path.abspath('../..')) # -- General configuration ---------------------------------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ 'sphinx.ext.autodoc', 'openstackdocstheme', ] # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. # execute "export SPHINX_DEBUG=1" in your terminal to disable # The suffix of source filenames. source_suffix = '.rst' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Murano Agent' copyright = u'2014, OpenStack Foundation' # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). add_module_names = True # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'native' # -- Options for HTML output -------------------------------------------------- # The theme to use for HTML and HTML Help pages. Major themes that come with # Sphinx are currently 'default' and 'sphinxdoc'. # html_theme_path = ["."] # html_theme = '_theme' # html_static_path = [] html_theme = 'openstackdocs' # openstackdocstheme options openstackdocs_repo_name = 'openstack/murano-agent' openstackdocs_auto_name = False openstackdocs_bug_project = 'murano' openstackdocs_bug_tag = '' # Output file base name for HTML help builder. htmlhelp_basename = '%sdoc' % project # -- Options for manual page output ------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [] # If true, show URL addresses after external links. man_show_urls = True ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/doc/source/index.rst0000664000175000017500000000003600000000000020045 0ustar00zuulzuul00000000000000.. include:: ../../README.rst ././@PaxHeader0000000000000000000000000000003300000000000011451 xustar000000000000000027 mtime=1648641201.220883 murano-agent-9.0.0/etc/0000775000175000017500000000000000000000000014713 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2368827 murano-agent-9.0.0/etc/muranoagent/0000775000175000017500000000000000000000000017233 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/etc/muranoagent/README-muranoagent.conf.txt0000664000175000017500000000021300000000000024167 0ustar00zuulzuul00000000000000To generate the sample muranoagent.conf file, run the following command from the top level of the murano-agent directory: tox -egenconfig ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2368827 murano-agent-9.0.0/etc/oslo-config-generator/0000775000175000017500000000000000000000000021116 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/etc/oslo-config-generator/muranoagent.conf0000664000175000017500000000021600000000000024304 0ustar00zuulzuul00000000000000[DEFAULT] output_file = etc/muranoagent/muranoagent.conf.sample namespace = muranoagent namespace = oslo.service.service namespace = oslo.log ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/lower-constraints.txt0000664000175000017500000000561400000000000020404 0ustar00zuulzuul00000000000000alembic==0.9.8 amqp==2.5.0 anyjson==0.3.3 appdirs==1.4.3 asn1crypto==0.24.0 attrs==17.4.0 automaton==1.14.0 bandit==1.1.0 cachetools==2.0.1 castellan==0.16.0 cffi==1.14.0 cliff==2.11.0 cmd2==0.8.1 colorama==0.3.9 coverage==4.0 cryptography==2.7 cursive==0.2.1 dataclasses==0.7 ddt==1.2.1 debtcollector==1.19.0 decorator==4.1.0 deprecation==2.0 dogpile.cache==0.6.5 enum-compat==0.0.2 eventlet==0.30.1 extras==1.0.0 fasteners==0.14.1 fixtures==3.0.0 future==0.16.0 futurist==1.8.0 gabbi==1.35.0 gitdb2==2.0.3 GitPython==3.0.5 greenlet==0.4.15 idna==2.6 iso8601==0.1.11 Jinja2==2.10 jmespath==0.9.3 jsonpatch==1.21 jsonpath-rw==1.4.0 jsonpath-rw-ext==1.1.3 jsonpointer==2.0 jsonschema==3.2.0 keystoneauth1==3.16.0 keystonemiddleware==4.20.0 kombu==4.6.1 linecache2==1.0.0 lxml==4.5.0 Mako==1.0.7 MarkupSafe==1.1.1 microversion-parse==0.2.1 mock==3.0.0 msgpack==0.6.0 msgpack-python==0.5.6 munch==2.2.0 mypy==0.761 netaddr==0.7.18 netifaces==0.10.4 networkx==2.1.0 numpy==1.19.0 openstacksdk==0.35.0 os-brick==4.3.1 os-client-config==1.29.0 os-resource-classes==0.4.0 os-service-types==1.7.0 os-traits==2.5.0 os-vif==1.14.0 os-win==5.4.0 os-xenapi==0.3.4 osc-lib==1.10.0 oslo.cache==1.26.0 oslo.concurrency==4.4.0 oslo.config==6.8.0 oslo.context==3.1.1 oslo.db==4.44.0 oslo.i18n==5.0.1 oslo.log==4.4.0 oslo.messaging==10.3.0 oslo.middleware==3.31.0 oslo.policy==3.6.0 oslo.privsep==2.4.0 oslo.reports==1.18.0 oslo.rootwrap==5.8.0 oslo.serialization==4.1.0 oslo.service==2.5.0 oslo.upgradecheck==1.3.0 oslo.utils==4.8.0 oslo.versionedobjects==1.35.0 oslo.vmware==2.17.0 oslotest==3.8.0 osprofiler==1.4.0 ovs==2.10.0 ovsdbapp==0.15.0 packaging==20.4 paramiko==2.7.1 Paste==2.0.2 PasteDeploy==1.5.0 pbr==5.5.1 pluggy==0.6.0 ply==3.11 prettytable==0.7.1 psutil==3.2.2 psycopg2-binary==2.8 py==1.5.2 pyasn1==0.4.2 pyasn1-modules==0.2.1 pycadf==2.7.0 pycparser==2.18 pyinotify==0.9.6 pyroute2==0.5.4 PyJWT==1.7.0 PyMySQL==0.8.0 pyOpenSSL==17.5.0 pyparsing==2.2.0 pyperclip==1.6.0 pypowervm==1.1.15 pytest==3.4.2 python-barbicanclient==4.5.2 python-cinderclient==3.3.0 python-dateutil==2.7.0 python-editor==1.0.3 python-glanceclient==2.8.0 python-ironicclient==3.0.0 python-keystoneclient==3.15.0 python-mimeparse==1.6.0 python-neutronclient==6.7.0 python-subunit==1.4.0 pytz==2018.3 PyYAML==5.1 repoze.lru==0.7 requests==2.25.1 requests-mock==1.2.0 requestsexceptions==1.4.0 retrying==1.3.3 rfc3986==1.2.0 Routes==2.3.1 semantic-version==2.6.0 simplejson==3.13.2 six==1.15.0 smmap2==2.0.3 sortedcontainers==2.1.0 SQLAlchemy==1.2.19 sqlalchemy-migrate==0.13.0 sqlparse==0.2.4 statsd==3.2.2 stestr==2.0.0 stevedore==1.20.0 suds-jurko==0.6 taskflow==3.8.0 Tempita==0.5.2 tenacity==6.3.1 testrepository==0.0.20 testresources==2.0.0 testscenarios==0.4 testtools==2.2.0 tooz==1.58.0 traceback2==1.4.0 unittest2==1.1.0 urllib3==1.22 vine==1.1.4 voluptuous==0.11.1 warlock==1.3.1 WebOb==1.8.2 websockify==0.9.0 wrapt==1.10.11 wsgi-intercept==1.7.0 zVMCloudConnector==1.3.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2368827 murano-agent-9.0.0/murano_agent.egg-info/0000775000175000017500000000000000000000000020311 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/PKG-INFO0000664000175000017500000000612100000000000021406 0ustar00zuulzuul00000000000000Metadata-Version: 1.2 Name: murano-agent Version: 9.0.0 Summary: Python Murano Agent Home-page: https://docs.openstack.org/murano/latest/ Author: OpenStack Author-email: openstack-discuss@lists.openstack.org License: Apache License, Version 2.0 Description: ======================== Team and repository tags ======================== .. image:: https://governance.openstack.org/tc/badges/murano-agent.svg :target: https://governance.openstack.org/tc/reference/tags/index.html .. Change things from this point on Murano Agent ============ Murano Agent is a VM-side guest agent that accepts commands from Murano engine and executes them. Image building using DiskImage-Builder -------------------------------------- Folder, named *contrib/elements* contains `diskimage-builder `_ elements to build an image which contains the Murano Agent required to use Murano. Ubuntu based image containing the agent can be built and uploaded to Glance with the following commands: :: $ git clone https://opendev.org/openstack/diskimage-builder.git $ git clone https://opendev.org/openstack/murano-agent.git $ export ELEMENTS_PATH=murano-agent/contrib/elements $ export DIB_CLOUD_INIT_DATASOURCES=OpenStack $ diskimage-builder/bin/disk-image-create vm ubuntu \ murano-agent -o ubuntu-murano-agent.qcow2 $ openstack image create ubuntu-murano --disk-format qcow2 --container-format bare --file ubuntu-murano-agent.qcow2 \ --property murano_image_info='{"title": "Ubuntu for Murano", "type": "linux"}' Project Resources ----------------- Project status, bugs, and blueprints are tracked on Launchpad: https://launchpad.net/murano Developer documentation can be found here: https://docs.openstack.org/murano/latest/ Additional resources are linked from the project wiki page: https://wiki.openstack.org/wiki/Murano License ------- Apache License Version 2.0 http://www.apache.org/licenses/LICENSE-2.0 Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: OpenStack Classifier: Intended Audience :: Developers Classifier: Intended Audience :: Information Technology Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: 3 :: Only Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Requires-Python: >=3.6 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/SOURCES.txt0000664000175000017500000001140000000000000022171 0ustar00zuulzuul00000000000000.stestr.conf .zuul.yaml AUTHORS CONTRIBUTING.rst ChangeLog HACKING.rst LICENSE README.rst lower-constraints.txt requirements.txt setup.cfg setup.py test-requirements.txt tox.ini contrib/c-demo-agent/Makefile contrib/c-demo-agent/Readme contrib/c-demo-agent/amqp.h contrib/c-demo-agent/amqp_framing.h contrib/c-demo-agent/amqp_ssl_socket.h contrib/c-demo-agent/amqp_tcp_socket.h contrib/c-demo-agent/lcfg_static.c contrib/c-demo-agent/lcfg_static.h contrib/c-demo-agent/librabbitmq.a contrib/c-demo-agent/murano-agent.c contrib/c-demo-agent/murano-agent.conf.example contrib/c-demo-agent/producer.c contrib/c-demo-agent/utils.c contrib/c-demo-agent/utils.h contrib/elements/readme.rst contrib/elements/murano-agent-debian/element-deps contrib/elements/murano-agent-debian/package-installs.yaml contrib/elements/murano-agent-debian/install.d/11-murano-agent-debian contrib/elements/murano-agent/install.d/74-murano-agent contrib/elements/murano-agent/install.d/murano-agent.conf contrib/elements/murano-agent/install.d/murano-agent.service contrib/windows-agent/README.rst contrib/windows-agent/WindowsAgent.sln contrib/windows-agent/ExecutionPlanGenerator/App.config contrib/windows-agent/ExecutionPlanGenerator/ExecutionPlanGenerator.csproj contrib/windows-agent/ExecutionPlanGenerator/Program.cs contrib/windows-agent/ExecutionPlanGenerator/packages.config contrib/windows-agent/ExecutionPlanGenerator/Properties/AssemblyInfo.cs contrib/windows-agent/WindowsAgent/App.config contrib/windows-agent/WindowsAgent/ExecutionPlan.cs contrib/windows-agent/WindowsAgent/Message.cs contrib/windows-agent/WindowsAgent/MessageSource.cs contrib/windows-agent/WindowsAgent/PlanExecutor.cs contrib/windows-agent/WindowsAgent/Program.cs contrib/windows-agent/WindowsAgent/SampleExecutionPlan.json contrib/windows-agent/WindowsAgent/ServiceManager.cs contrib/windows-agent/WindowsAgent/SignatureVerifier.cs contrib/windows-agent/WindowsAgent/WindowsAgent.csproj contrib/windows-agent/WindowsAgent/WindowsService.cs contrib/windows-agent/WindowsAgent/WindowsServiceInstaller.cs contrib/windows-agent/WindowsAgent/packages.config contrib/windows-agent/WindowsAgent/Properties/AssemblyInfo.cs doc/requirements.txt doc/source/conf.py doc/source/index.rst etc/muranoagent/README-muranoagent.conf.txt etc/oslo-config-generator/muranoagent.conf murano_agent.egg-info/PKG-INFO murano_agent.egg-info/SOURCES.txt murano_agent.egg-info/dependency_links.txt murano_agent.egg-info/entry_points.txt murano_agent.egg-info/not-zip-safe murano_agent.egg-info/pbr.json murano_agent.egg-info/requires.txt murano_agent.egg-info/top_level.txt muranoagent/__init__.py muranoagent/app.py muranoagent/bunch.py muranoagent/exceptions.py muranoagent/execution_plan_queue.py muranoagent/execution_plan_runner.py muranoagent/execution_result.py muranoagent/files_manager.py muranoagent/opts.py muranoagent/script_runner.py muranoagent/util.py muranoagent/validation.py muranoagent/version.py muranoagent/win32.py muranoagent/cmd/__init__.py muranoagent/cmd/run.py muranoagent/common/__init__.py muranoagent/common/config.py muranoagent/common/messaging/__init__.py muranoagent/common/messaging/message.py muranoagent/common/messaging/mqclient.py muranoagent/common/messaging/subscription.py muranoagent/executors/__init__.py muranoagent/executors/chef_puppet_executor_base.py muranoagent/executors/application/__init__.py muranoagent/executors/chef/__init__.py muranoagent/executors/puppet/__init__.py muranoagent/tests/__init__.py muranoagent/tests/unit/__init__.py muranoagent/tests/unit/base.py muranoagent/tests/unit/execution_plan.py muranoagent/tests/unit/test_agent.py muranoagent/tests/unit/test_app.py muranoagent/tests/unit/test_execution_plan_queue.py muranoagent/tests/unit/test_files_manager.py muranoagent/tests/unit/test_script_runner.py muranoagent/tests/unit/test_util.py muranoagent/tests/unit/executors/__init__.py muranoagent/tests/unit/executors/test_chef.py muranoagent/tests/unit/executors/test_puppet.py releasenotes/notes/.placeholder releasenotes/notes/drop-py-2-7-33ea9091c6530815.yaml releasenotes/notes/fix-1591614-1b2db4cbb41f411c.yaml releasenotes/notes/install-chef-d67f115c0958c116.yaml releasenotes/notes/python3-54ba2f6e70795ba6.yaml releasenotes/notes/python3-base64-usage-aeef2270be7bdf26.yaml releasenotes/source/conf.py releasenotes/source/index.rst releasenotes/source/liberty.rst releasenotes/source/mitaka.rst releasenotes/source/newton.rst releasenotes/source/ocata.rst releasenotes/source/pike.rst releasenotes/source/queens.rst releasenotes/source/rocky.rst releasenotes/source/stein.rst releasenotes/source/train.rst releasenotes/source/unreleased.rst releasenotes/source/ussuri.rst releasenotes/source/victoria.rst releasenotes/source/wallaby.rst releasenotes/source/xena.rst releasenotes/source/_static/.placeholder releasenotes/source/_templates/.placeholder././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/dependency_links.txt0000664000175000017500000000000100000000000024357 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/entry_points.txt0000664000175000017500000000016700000000000023613 0ustar00zuulzuul00000000000000[console_scripts] muranoagent = muranoagent.cmd.run:main [oslo.config.opts] muranoagent = muranoagent.opts:list_opts ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/not-zip-safe0000664000175000017500000000000100000000000022537 0ustar00zuulzuul00000000000000 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/pbr.json0000664000175000017500000000005600000000000021770 0ustar00zuulzuul00000000000000{"git_version": "b873684", "is_release": true}././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/requires.txt0000664000175000017500000000033100000000000022706 0ustar00zuulzuul00000000000000GitPython>=3.0.5 PyYAML>=5.1 anyjson>=0.3.3 cryptography>=2.7 eventlet>=0.30.1 kombu>=4.6.1 oslo.config>=6.8.0 oslo.log>=4.4.0 oslo.service>=2.5.0 oslo.utils>=4.8.0 pbr>=5.5.1 requests>=2.25.1 semantic-version>=2.6.0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641201.0 murano-agent-9.0.0/murano_agent.egg-info/top_level.txt0000664000175000017500000000001400000000000023036 0ustar00zuulzuul00000000000000muranoagent ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/0000775000175000017500000000000000000000000016460 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/__init__.py0000664000175000017500000000000000000000000020557 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/app.py0000664000175000017500000001371000000000000017614 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os import sys import time from oslo_log import log as logging from oslo_service import service from oslo_utils import strutils from muranoagent.common import config from muranoagent.common import messaging from muranoagent import execution_plan_queue from muranoagent import execution_plan_runner from muranoagent import execution_result as ex_result from muranoagent import validation CONF = config.CONF LOG = logging.getLogger(__name__) class MuranoAgent(service.Service): def __init__(self): self._queue = execution_plan_queue.ExecutionPlanQueue() super(MuranoAgent, self).__init__() @staticmethod def _load_package(name): try: LOG.debug('Loading plugin %s', name) __import__(name) except Exception: LOG.warning('Cannot load package %s', name, exc_info=True) pass def _load(self): path = os.path.join(os.path.dirname(__file__), 'executors') sys.path.insert(1, path) for entry in os.listdir(path): package_path = os.path.join(path, entry) if os.path.isdir(package_path): MuranoAgent._load_package(entry) def start(self): self._load() msg_iterator = self._wait_plan() while True: try: self._loop_func(msg_iterator) except Exception as ex: LOG.exception(ex) time.sleep(5) def _loop_func(self, msg_iterator): result, timestamp = self._queue.get_execution_plan_result() if result is not None: if self._send_result(result): self._queue.remove(timestamp) return plan = self._queue.get_execution_plan() if plan is not None: LOG.debug("Got an execution plan '{0}':".format( strutils.mask_password(str(plan)))) if self._verify_plan(plan): self._run(plan) return next(msg_iterator) def _verify_plan(self, plan): try: validation.validate_plan(plan) return True except Exception as err: try: execution_result = ex_result.ExecutionResult.from_error( err, plan) if 'ReplyTo' in plan and CONF.enable_dynamic_result_queue: execution_result['ReplyTo'] = plan.ReplyTo self._send_result(execution_result) except ValueError: LOG.warning('Execution result is not produced') finally: return False def _run(self, plan): try: with execution_plan_runner.ExecutionPlanRunner(plan) as runner: result = runner.run() execution_result = ex_result.ExecutionResult.from_result( result, plan) self._queue.put_execution_result(execution_result, plan) except Exception as ex: LOG.exception('Error running execution plan') execution_result = ex_result.ExecutionResult.from_error(ex, plan) self._queue.put_execution_result(execution_result, plan) def _send_result(self, result): with self._create_rmq_client() as mq: msg = messaging.Message() msg.body = result msg.id = result.get('SourceID') routing_key = CONF.rabbitmq.result_routing_key if ('ReplyTo' in result) and CONF.enable_dynamic_result_queue: routing_key = result.pop('ReplyTo') mq.send(message=msg, key=routing_key, exchange=CONF.rabbitmq.result_exchange) return True def _create_rmq_client(self): rabbitmq = CONF.rabbitmq connection_params = { 'login': rabbitmq.login, 'password': rabbitmq.password, 'host': rabbitmq.host, 'port': rabbitmq.port, 'virtual_host': rabbitmq.virtual_host, 'ssl': rabbitmq.ssl, 'ssl_version': rabbitmq.ssl_version, 'ca_certs': rabbitmq.ca_certs.strip() or None, 'insecure': rabbitmq.insecure } return messaging.MqClient(**connection_params) def _wait_plan(self): delay = 5 while True: try: with self._create_rmq_client() as mq: with mq.open(CONF.rabbitmq.input_queue, prefetch_count=1) as subscription: while True: msg = subscription.get_message(timeout=5) if msg is not None: try: self._queue.put_execution_plan( msg.body, msg.signature, msg.id, msg.reply_to) finally: msg.ack() delay = 5 if msg is not None: yield except KeyboardInterrupt: break except Exception: LOG.warning('Communication error', exc_info=True) time.sleep(delay) delay = min(delay * 1.2, 60) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/bunch.py0000664000175000017500000000172600000000000020137 0ustar00zuulzuul00000000000000# Copyright (c) 2014 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. class Bunch(dict): """Bunch dict/object-like container. Bunch container provides both dictionary-like and object-like attribute access. """ def __getattr__(self, item): return self.__getitem__(item) def __setattr__(self, key, value): return self.__setitem__(key, value) def __delattr__(self, key): del self[key] ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/cmd/0000775000175000017500000000000000000000000017223 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/cmd/__init__.py0000664000175000017500000000000000000000000021322 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/cmd/run.py0000664000175000017500000000412400000000000020402 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # flake8: noqa: E402 import os import sys # If ../muranoagent/__init__.py exists, add ../ to Python search path, so # it will override what happens to be installed in /usr/(local/)lib/python... possible_topdir = os.path.normpath(os.path.join(os.path.abspath(__file__), os.pardir, os.pardir, os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'muranoagent', '__init__.py')): sys.path.insert(0, possible_topdir) import eventlet eventlet.monkey_patch() # Monkey patch the original current_thread to use the up-to-date _active # global variable. See https://bugs.launchpad.net/bugs/1863021 and # https://github.com/eventlet/eventlet/issues/592 import __original_module_threading as orig_threading import threading # noqa orig_threading.current_thread.__globals__['_active'] = threading._active from oslo_config import cfg from oslo_log import log as logging from oslo_service import service from muranoagent import app from muranoagent.common import config CONF = cfg.CONF def main(): try: config.parse_args() logging.setup(CONF, 'muranoagent') launcher = service.ServiceLauncher(CONF) launcher.launch_service(app.MuranoAgent()) launcher.wait() except RuntimeError as e: sys.stderr.write("ERROR: %s\n" % e) sys.exit(1) if __name__ == '__main__': main() ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/common/0000775000175000017500000000000000000000000017750 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/common/__init__.py0000664000175000017500000000000000000000000022047 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/common/config.py0000664000175000017500000000653700000000000021602 0ustar00zuulzuul00000000000000# Copyright 2011 OpenStack LLC. # All Rights Reserved. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. """ Routines for configuring Murano-Agent """ from oslo_config import cfg from oslo_log import log as logging from muranoagent import version CONF = cfg.CONF opts = [ cfg.StrOpt('storage', default='/var/murano/plans', help='Directory to store execution plans'), cfg.StrOpt('engine_key', help='Public key of murano-engine') ] message_routing_opt = cfg.BoolOpt( 'enable_dynamic_result_queue', help='Enable taking dynamic result queue from task field reply_to', default=False) rabbit_opts = [ cfg.HostAddressOpt('host', help='The RabbitMQ broker address which used for ' 'communication with Murano guest agents.', default='localhost'), cfg.IntOpt('port', help='The RabbitMQ broker port.', default=5672), cfg.StrOpt('login', help='The RabbitMQ login.', default='guest'), cfg.StrOpt('password', help='The RabbitMQ password.', secret=True, default='guest'), cfg.StrOpt('virtual_host', help='The RabbitMQ virtual host.', default='/'), cfg.BoolOpt('ssl', help='Boolean flag to enable SSL communication through the ' 'RabbitMQ broker between murano-engine and guest agents.', default=False), cfg.StrOpt('ssl_version', default='', help='SSL version to use (valid only if SSL enabled). ' 'Valid values are TLSv1 and SSLv23. SSLv2, SSLv3, ' 'TLSv1_1, and TLSv1_2 may be available on some ' 'distributions.'), cfg.StrOpt('ca_certs', help='SSL cert file (valid only if SSL enabled).', default=''), cfg.BoolOpt('insecure', default=False, help='This option explicitly allows Murano to perform ' '"insecure" SSL connections to RabbitMQ'), cfg.StrOpt('result_routing_key', help='This value should be obtained from API'), cfg.StrOpt('result_exchange', help='This value must be obtained from API', default=''), cfg.StrOpt('input_queue', help='This value must be obtained from API', default='') ] CONF.register_opts(opts) CONF.register_cli_opt(message_routing_opt) CONF.register_opts(rabbit_opts, group='rabbitmq') logging.register_options(CONF) def parse_args(args=None, usage=None, default_config_files=None): version_string = version.version_info.version_string() CONF(args=args, project='muranoagent', version=version_string, usage=usage, default_config_files=default_config_files) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/common/messaging/0000775000175000017500000000000000000000000021725 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/common/messaging/__init__.py0000664000175000017500000000151100000000000024034 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. from muranoagent.common.messaging.message import Message # noqa from muranoagent.common.messaging.mqclient import MqClient # noqa from muranoagent.common.messaging.subscription import Subscription # noqa __all__ = ['Message', 'Subscription', 'MqClient'] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/common/messaging/message.py0000664000175000017500000000337100000000000023727 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. from oslo_log import log as logging LOG = logging.getLogger("murano-common.messaging") class Message(object): def __init__(self, connection=None, message_handle=None): self._body = None self._connection = connection self._message_handle = message_handle if message_handle: self.id = message_handle.properties.get('message_id') self._reply_to = message_handle.properties.get('reply_to') self._signature = message_handle.headers.get('signature') else: self.id = None self._reply_to = None self._signature = None if message_handle: self.body = message_handle.body else: self.body = None @property def body(self): return self._body @body.setter def body(self, value): self._body = value @property def id(self): return self._id @id.setter def id(self, value): self._id = value or '' @property def reply_to(self): return self._reply_to def ack(self): self._message_handle.ack() @property def signature(self): return self._signature ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/common/messaging/mqclient.py0000664000175000017500000001156500000000000024123 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import random import ssl as ssl_module import anyjson import eventlet import kombu from oslo_service import sslutils from muranoagent.common.messaging import subscription class MqClient(object): def __init__(self, login, password, host, port, virtual_host, ssl=False, ssl_version=None, ca_certs=None, insecure=False): ssl_params = None if ssl: cert_reqs = ssl_module.CERT_REQUIRED if insecure: if ca_certs: cert_reqs = ssl_module.CERT_OPTIONAL else: cert_reqs = ssl_module.CERT_NONE ssl_params = { 'ca_certs': ca_certs, 'cert_reqs': cert_reqs } if ssl_version: key = ssl_version.lower() try: ssl_params['ssl_version'] = sslutils._SSL_PROTOCOLS[key] except KeyError: raise RuntimeError("Invalid SSL version: %s" % ssl_version) # Time interval after which RabbitMQ will disconnect client if no # heartbeats were received. Usually client sends 2 heartbeats during # this interval. Using random to make it less lucky that many agents # ping RabbitMQ simultaneously heartbeat_rate = 20 + 20 * random.random() self._connection = kombu.Connection( 'amqp://{0}:{1}@{2}:{3}/{4}'.format( login, password, host, port, virtual_host ), ssl=ssl_params, heartbeat=heartbeat_rate ) self._channel = None self._connected = False self._exception = None def __enter__(self): self.connect() return self def __exit__(self, exc_type, exc_val, exc_tb): if exc_type: self._connected = False else: self.close() return False def connect(self): self._connection.connect() self._channel = self._connection.channel() if not self._connected: self._connected = True eventlet.spawn(self._heartbeater) def close(self): if self._connected: self._connection.close() self._connected = False def _check_exception(self): ex = self._exception if ex: self._exception = None raise ex def _heartbeater(self): while self._connected: eventlet.sleep(1) try: self._connection.heartbeat_check() except Exception as ex: self._exception = ex self._connected = False def declare(self, queue, exchange='', enable_ha=False, ttl=0): self._check_exception() if not self._connected: raise RuntimeError('Not connected to RabbitMQ') queue_arguments = {} if enable_ha is True: # To use mirrored queues feature in RabbitMQ 2.x # we need to declare this policy on the queue itself. # # Warning: this option has no effect on RabbitMQ 3.X, # to enable mirrored queues feature in RabbitMQ 3.X, please # configure RabbitMQ. queue_arguments['x-ha-policy'] = 'all' if ttl > 0: queue_arguments['x-expires'] = ttl exchange = kombu.Exchange(exchange, type='direct', durable=True) queue = kombu.Queue(queue, exchange, queue, durable=False, queue_arguments=queue_arguments) bound_queue = queue(self._connection) bound_queue.declare() def send(self, message, key, exchange=''): self._check_exception() if not self._connected: raise RuntimeError('Not connected to RabbitMQ') producer = kombu.Producer(self._connection) producer.publish( exchange=str(exchange), routing_key=str(key), body=anyjson.dumps(message.body), message_id=str(message.id) ) def open(self, queue, prefetch_count=1): self._check_exception() if not self._connected: raise RuntimeError('Not connected to RabbitMQ') return subscription.Subscription(self._connection, queue, prefetch_count, self._check_exception) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/common/messaging/subscription.py0000664000175000017500000000443600000000000025032 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import collections import socket import time import kombu from muranoagent.common.messaging import message class Subscription(object): def __init__(self, connection, queue, prefetch_count, exception_func): self._buffer = collections.deque() self._connection = connection self._queue = kombu.Queue(name=queue, exchange=None) self._consumer = kombu.Consumer(self._connection, auto_declare=False) self._consumer.register_callback(self._receive) self._consumer.qos(prefetch_count=prefetch_count) self._check_exception = exception_func def __enter__(self): self._consumer.add_queue(self._queue) self._consumer.consume() return self def __exit__(self, exc_type, exc_val, exc_tb): if self._consumer is not None and not exc_type: self._consumer.cancel() return False def get_message(self, timeout=None): self._check_exception() msg_handle = self._get(timeout=timeout) if msg_handle is None: return None return message.Message(self._connection, msg_handle) def _get(self, timeout=None): self._check_exception() elapsed = 0.0 remaining = timeout while True: time_start = time.time() if self._buffer: return self._buffer.pop() try: self._connection.drain_events(timeout=timeout and remaining) except socket.timeout: return None elapsed += time.time() - time_start remaining = timeout and timeout - elapsed or None def _receive(self, message_data, message): self._check_exception() self._buffer.append(message) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/exceptions.py0000664000175000017500000000231300000000000021212 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. class AgentException(Exception): def __init__(self, code, message=None, additional_data=None): self._error_code = code self._additional_data = additional_data super(AgentException, self).__init__(message) @property def error_code(self): return self._error_code @property def additional_data(self): return self._additional_data class CustomException(AgentException): def __init__(self, code, message=None, additional_data=None): super(CustomException, self).__init__( code + 100, message, additional_data) class IncorrectFormat(AgentException): pass ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/execution_plan_queue.py0000664000175000017500000001327500000000000023263 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import json import os import shutil import time from cryptography.hazmat import backends from cryptography.hazmat.primitives.asymmetric import padding from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives import serialization from oslo_log import log as logging from muranoagent import bunch from muranoagent.common import config from muranoagent import util CONF = config.CONF LOG = logging.getLogger(__name__) class ExecutionPlanQueue(object): plan_filename = 'plan.json' result_filename = 'result.json' stamp_filename = 'stamp' def __init__(self): self._plans_folder = os.path.join(CONF.storage, 'plans') if not os.path.exists(self._plans_folder): os.makedirs(self._plans_folder, 0o700) else: try: os.chmod(self._plans_folder, 0o700) except OSError: pass self._key = None if not CONF.engine_key \ else serialization.load_pem_public_key( CONF.engine_key, backends.default_backend()) self._load_stamp() def put_execution_plan(self, execution_plan, signature, msg_id, reply_to): timestamp = str(int(time.time() * 10000)) # execution_plan['_timestamp'] = timestamp folder_path = os.path.join(self._plans_folder, timestamp) os.mkdir(folder_path) plan_file_path = os.path.join( folder_path, ExecutionPlanQueue.plan_filename) json_plan = json.dumps({ 'Data': util.b64encode(execution_plan), 'Signature': util.b64encode(signature or ''), 'ID': msg_id, 'ReplyTo': reply_to }) with open(plan_file_path, 'wb') as out_file: out_file.write(json_plan) def _get_first_timestamp(self, filename): def predicate(folder): path = os.path.join(self._plans_folder, folder, filename) return os.path.exists(path) timestamps = [ name for name in os.listdir(self._plans_folder) if predicate(name) ] timestamps.sort() return None if len(timestamps) == 0 else timestamps[0] def _get_first_file(self, filename): timestamp = self._get_first_timestamp(filename) if not timestamp: return None, None path = os.path.join(self._plans_folder, timestamp, filename) with open(path) as json_file: return json.loads(json_file.read()), timestamp def get_execution_plan(self): while True: ep_info, timestamp = self._get_first_file( ExecutionPlanQueue.plan_filename) if ep_info is None: return None try: data = util.b64decode(ep_info['Data']) if self._key: signature = util.b64decode(ep_info['Signature']) self._verify_signature(data, signature) ep = json.loads(data) if not isinstance(ep, dict): raise ValueError('Message is not a document') stamp = ep.get('Stamp', -1) if stamp >= 0: if stamp <= self._last_stamp: raise ValueError('Dropping old/duplicate message') self._save_stamp(stamp) if 'ID' not in ep: ep['ID'] = ep_info['ID'] if 'ReplyTo' not in ep: ep['ReplyTo'] = ep_info['ReplyTo'] ep['_timestamp'] = timestamp return bunch.Bunch(ep) except Exception as ex: LOG.exception(ex) self.remove(timestamp) def _verify_signature(self, data, signature): if not signature: raise ValueError("Required signature was not found") self._key.verify( signature, CONF.rabbitmq.input_queue + data, padding.PKCS1v15(), hashes.SHA256()) def put_execution_result(self, result, execution_plan): timestamp = execution_plan['_timestamp'] if 'ReplyTo' in execution_plan: result['ReplyTo'] = execution_plan.get('ReplyTo') path = os.path.join( self._plans_folder, timestamp, ExecutionPlanQueue.result_filename) with open(path, 'w') as out_file: out_file.write(json.dumps(result)) def remove(self, timestamp): path = os.path.join(self._plans_folder, timestamp) shutil.rmtree(path) def get_execution_plan_result(self): return self._get_first_file( ExecutionPlanQueue.result_filename) def _load_stamp(self): plan_file_path = os.path.join( self._plans_folder, ExecutionPlanQueue.stamp_filename) if os.path.exists(plan_file_path): with open(plan_file_path) as f: self._last_stamp = int(f.read()) else: self._last_stamp = 0 def _save_stamp(self, stamp): plan_file_path = os.path.join( self._plans_folder, ExecutionPlanQueue.stamp_filename) with open(plan_file_path, 'w') as f: f.write(str(stamp)) self._last_stamp = stamp ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/execution_plan_runner.py0000664000175000017500000000517000000000000023443 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import sys from muranoagent import bunch from muranoagent import files_manager as fm from muranoagent import script_runner class ExecutionPlanRunner(object): def __init__(self, execution_plan): self._execution_plan = execution_plan self._main_script = self._prepare_script(execution_plan.Body) self._script_funcs = {} self._files_manager = fm.FilesManager(execution_plan) self._prepare_executors(execution_plan) def run(self): script_globals = { "args": bunch.Bunch(self._execution_plan.get('Parameters') or {}) } script_globals.update(self._script_funcs) exec(self._main_script, script_globals) if '__execution_plan_exception' in script_globals: raise script_globals['__execution_plan_exception'] return script_globals['__execution_plan_result'] @staticmethod def _unindent(script, initial_indent): lines = script.expandtabs(4).split('\n') min_indent = sys.maxsize for line in lines: indent = -1 for i, c in enumerate(line): if c != ' ': indent = i break if 0 <= indent < min_indent: min_indent = indent return '\n'.join([' ' * initial_indent + line[min_indent:] for line in lines]) def _prepare_executors(self, execution_plan): for key, value in execution_plan.Scripts.items(): self._script_funcs[key] = script_runner.ScriptRunner( key, bunch.Bunch(value), self._files_manager) @staticmethod def _prepare_script(body): script = 'def __execution_plan_main():\n' script += ExecutionPlanRunner._unindent(body, 4) script += """ try: __execution_plan_result = __execution_plan_main() except Exception as e: __execution_plan_exception = e """ return script def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self._files_manager.clear() return False ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/execution_result.py0000664000175000017500000000420000000000000022427 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. from oslo_utils import timeutils from oslo_utils import uuidutils from muranoagent import exceptions as exc class ExecutionResult(object): @staticmethod def from_result(result, execution_plan): if 'ID' not in execution_plan: raise ValueError('ID attribute is missing from execution plan') return { 'FormatVersion': '2.0.0', 'ID': uuidutils.generate_uuid(dashed=False), 'SourceID': execution_plan.ID, 'Action': 'Execution:Result', 'ErrorCode': 0, 'Body': result, 'Time': str(timeutils.utcnow()) } @staticmethod def from_error(error, execution_plan): if 'ID' not in execution_plan: raise ValueError('ID attribute is missing from execution plan') error_code = 1 additional_info = None message = None if isinstance(error, int): error_code = error elif isinstance(error, Exception): message = str(error) if isinstance(error, exc.AgentException): error_code = error.error_code additional_info = error.additional_data return { 'FormatVersion': '2.0.0', 'ID': uuidutils.generate_uuid(dashed=False), 'SourceID': execution_plan.ID, 'Action': 'Execution:Result', 'ErrorCode': error_code, 'Body': { 'Message': message, 'AdditionalInfo': additional_info }, 'Time': str(timeutils.utcnow()) } ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/executors/0000775000175000017500000000000000000000000020501 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/executors/__init__.py0000664000175000017500000000204100000000000022607 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. class ExecutorsRepo(object): def __init__(self): self._executors = {} def register_executor(self, name, cls): self._executors[name] = cls def create_executor(self, type, name): if type not in self._executors: return None return self._executors[type](name) Executors = ExecutorsRepo() def executor(name): def wrapper(cls): Executors.register_executor(name, cls) return cls return wrapper ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/executors/application/0000775000175000017500000000000000000000000023004 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/executors/application/__init__.py0000664000175000017500000000636300000000000025125 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os import signal import stat import subprocess import sys from oslo_log import log as logging from muranoagent import bunch import muranoagent.exceptions from muranoagent import executors LOG = logging.getLogger(__name__) @executors.executor('Application') class ApplicationExecutor(object): def __init__(self, name): self._name = name def load(self, path, options): self._path = path self._capture_stdout = options.get('captureStdout', True) self._capture_stderr = options.get('captureStderr', True) self._verify_exitcode = options.get('verifyExitcode', True) def run(self, function, commandline='', input=None): dir_name = os.path.dirname(self._path) os.chdir(dir_name) app = '"{0}" {1}'.format(os.path.basename(self._path), commandline) if not sys.platform == 'win32': os.chmod(self._path, stat.S_IEXEC | stat.S_IREAD) app = './' + app stdout = subprocess.PIPE if self._capture_stdout else None stderr = subprocess.PIPE if self._capture_stderr else None script_name = os.path.relpath(self._path) LOG.debug("Starting '{0}' script execution".format(script_name)) popen_kwargs = { 'stdout': stdout, 'stderr': stderr, 'universal_newlines': True, 'cwd': dir_name, 'shell': True } if os.name != 'nt': popen_kwargs['preexec_fn'] = lambda: signal.signal( signal.SIGPIPE, signal.SIG_DFL) process = subprocess.Popen(app, **popen_kwargs) stdout, stderr = process.communicate(input) retcode = process.poll() LOG.debug("Script {0} execution finished " "with retcode: {1}".format(script_name, retcode)) if stdout is not None: if hasattr(stdout, 'decode'): stdout = stdout.decode('utf-8') LOG.debug(u"'{0}' execution stdout: " u"'{1}'".format(script_name, stdout)) if stderr is not None: if hasattr(stderr, 'decode'): stderr = stderr.decode('utf-8') LOG.debug(u"'{0}' execution stderr: " u"'{1}'".format(script_name, stderr)) result = { 'exitCode': retcode, 'stdout': stdout.strip() if stdout else None, 'stderr': stderr.strip() if stderr else None } if self._verify_exitcode and retcode != 0: raise muranoagent.exceptions.CustomException( 0, message='Script {0} returned error code'.format(self._name), additional_data=result) return bunch.Bunch(result) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/executors/chef/0000775000175000017500000000000000000000000021406 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/executors/chef/__init__.py0000664000175000017500000001152400000000000023522 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import json import os import subprocess from oslo_log import log as logging from muranoagent import bunch import muranoagent.exceptions from muranoagent import executors from muranoagent.executors import chef_puppet_executor_base LOG = logging.getLogger(__name__) @executors.executor('Chef') class ChefExecutor(chef_puppet_executor_base.ChefPuppetExecutorBase): def load(self, path, options): super(ChefExecutor, self).load(path, options) self._use_berkshelf = options.get('useBerkshelf', False) self._berksfile_path = options.get('berksfilePath', None) def run(self, function, recipe_attributes=None, input=None): """It runs the chef executor. :param function: The function :param recipe_attributes: recipe attributes :param input: """ self._valid_module_name() cookbook_path = self._create_cookbook_path(self.module_name) try: self._configure_chef(cookbook_path) self._generate_manifest(self.module_name, self.module_recipe, recipe_attributes) except Exception as e: result = { 'exitCode': 2, 'stdout': None, 'stderr': e.strerror } raise muranoagent.exceptions.CustomException( 0, message='Cookbook {0} returned error code {1}: {2}'.format( self.module_name, self.module_recipe, e.strerror, ), additional_data=result) solo_file = os.path.join(self._path, "solo.rb") command = 'chef-solo -j node.json -c {0}'.format(solo_file) result = self._execute_command(command) return bunch.Bunch(result) def _create_cookbook_path(self, cookbook_name): """It defines a path where all required cookbooks are located.""" path = os.path.abspath(self._path) if self._use_berkshelf: LOG.debug('Using Berkshelf') # Get Berksfile if self._berksfile_path is None: self._berksfile_path = cookbook_name + '/Berksfile' berksfile = os.path.join(path, self._berksfile_path) if not os.path.isfile(berksfile): msg = "Berskfile {0} not found".format(berksfile) LOG.debug(msg) raise muranoagent.exceptions.CustomException( 0, message=msg, additional_data=None) # Create cookbooks path cookbook_path = os.path.join(path, "berks-cookbooks") if not os.path.isdir(cookbook_path): os.makedirs(cookbook_path) # Vendor cookbook and its dependencies to cookbook_path command = 'berks vendor --berksfile={0} {1}'.format( berksfile, cookbook_path) result = self._execute_command(command) if result['exitCode'] != 0: raise muranoagent.exceptions.CustomException( 0, message='Berks returned error code', additional_data=result) return cookbook_path else: return path def _configure_chef(self, cookbook_path): """It generates the chef files for configuration.""" solo_file = os.path.join(self._path, 'solo.rb') if not os.path.exists(solo_file): if not os.path.isdir(self._path): os.makedirs(self._path) with open(solo_file, "w+") as f: f.write('cookbook_path \"' + cookbook_path + '\"') def _generate_manifest(self, cookbook_name, cookbook_recipe, recipe_attributes): """It generates the chef manifest.""" node = self._create_manifest(cookbook_name, cookbook_recipe, recipe_attributes) with open("node.json", "w+") as f: f.write(node) def _create_manifest(self, cookbook_name, cookbook_recipe, recipe_attributes): node = {} node["run_list"] = [u"recipe[{0}::{1}]".format( cookbook_name, cookbook_recipe)] if recipe_attributes: node[cookbook_name] = recipe_attributes.copy() return json.dumps(node) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/executors/chef_puppet_executor_base.py0000664000175000017500000000652600000000000026276 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import json import os import subprocess from oslo_log import log as logging from muranoagent import bunch import muranoagent.exceptions from muranoagent import executors LOG = logging.getLogger(__name__) class ChefPuppetExecutorBase(object): def __init__(self, name): self._name = name def load(self, path, options): """Load the path and options from template into the executor. :param path: The path :param options: execution plan options. """ self._path = path self._capture_stdout = options.get('captureStdout', True) self._capture_stderr = options.get('captureStderr', True) self._verify_exitcode = options.get('verifyExitcode', True) def _valid_module_name(self): if not self._valid_name(self._name): msg = ("Module recipe name format {0} is not valid". format(self._name)) LOG.debug(msg) raise muranoagent.exceptions.CustomException( 0, message=msg, additional_data=None) self.module_name = self._name[0:self._name.rfind('::')] self.module_recipe = self._name[self._name.rfind('::') + 2:] def _valid_name(self, name): return '::' in name def _execute_command(self, command): stdout = subprocess.PIPE if self._capture_stdout else None stderr = subprocess.PIPE if self._capture_stderr else None process = subprocess.Popen( command, stdout=stdout, stderr=stderr, universal_newlines=True, cwd=os.getcwd(), shell=True) stdout, stderr = process.communicate(input) retcode = process.poll() if stdout is not None: if not isinstance(stdout, str): stdout = stdout.decode('utf-8') LOG.debug(u"'{0}' execution stdout: " u"'{1}'".format(self.module_name, stdout)) if stderr is not None: for line in stdout.splitlines(): if 'ERROR' in line: stderr += line + "\n" LOG.debug(u"'{0}' execution stderr: " u"'{1}'".format(self.module_name, stderr)) LOG.debug('Script {0} execution finished \ with retcode: {1} {2}'.format(self.module_name, retcode, stderr)) result = { 'exitCode': retcode, 'stdout': stdout.strip() if stdout else None, 'stderr': stderr.strip() if stderr else None } if self._verify_exitcode and retcode != 0: raise muranoagent.exceptions.CustomException( 0, message='Script {0} returned error code'.format(self._name), additional_data=result) return result ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/executors/puppet/0000775000175000017500000000000000000000000022016 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/executors/puppet/__init__.py0000664000175000017500000000657600000000000024145 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os import subprocess import yaml from muranoagent import bunch import muranoagent.exceptions from muranoagent import executors from muranoagent.executors import chef_puppet_executor_base @executors.executor('Puppet') class PuppetExecutor(chef_puppet_executor_base.ChefPuppetExecutorBase): def run(self, function, recipe_attributes=None, input=None): """It runs the puppet executor. :param function: The function :param recipe_attributes: recipe attributes :param input: """ self._valid_module_name() try: self._configure_puppet() self._generate_files(self.module_name, self.module_recipe, recipe_attributes) except Exception as e: result = { 'exitCode': 2, 'stdout': None, 'stderr': e.strerror } raise muranoagent.exceptions.CustomException( 0, message='Module %s returned error code %s: %s' % (self.module_name, self.module_recipe, e.strerror), additional_data=result) command = 'puppet apply --hiera_config=hiera.yaml --modulepath ' \ '{0} manifest.pp'.format(self._path) result = self._execute_command(command) return bunch.Bunch(result) def _configure_puppet(self): if os.path.exists('hiera.yaml'): return data = dict( backends='yaml', logger='console', hierarchy='%{env}', yaml=dict(datadir='/etc/puppet/hieradata') ) self._write_yaml_file('hiera.yaml', data) def _generate_files(self, module, module_recipe, recipe_attributes): manifest = self._create_manifest(module, module_recipe) with open("manifest.pp", "w+") as f: f.write(str(manifest)) if recipe_attributes is None: return hiera_data = self._create_hiera_data(module, recipe_attributes) self._write_yaml_file('default.yaml', hiera_data) def _create_manifest(self, module_name, module_recipe): if len(module_recipe) == 0: return "node 'default' {{ class {{ {0}:}}}}".format(module_name) return "node 'default' {{ class {{ {0}::{1}:}}}}".\ format(module_name, module_recipe) def _create_hiera_data(self, cookbook_name, recipe_attributes): if recipe_attributes is None: return atts = {} for att_name, att_value in recipe_attributes.items(): atts[cookbook_name + '::' + att_name] = att_value return atts def _write_yaml_file(self, file, data): with open(file, 'w') as outfile: outfile.write(yaml.dump(data, default_flow_style=False)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/files_manager.py0000664000175000017500000001464700000000000021642 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import git import os import re import requests import shutil import subprocess from oslo_log import log as logging from oslo_utils import encodeutils import urllib from muranoagent.common import config from muranoagent import util CONF = config.CONF LOG = logging.getLogger(__name__) class FilesManager(object): def __init__(self, execution_plan): self._fetched_files = {} self._files = execution_plan.get('Files') or {} self._cache_folder = os.path.join( CONF.storage, 'files', execution_plan.ID) if os.path.exists(self._cache_folder): self.clear() os.makedirs(self._cache_folder, 0o700) def put_file(self, file_id, script): if type(file_id) is dict: file_name = list(file_id.keys())[0] file_def = file_id[file_name] else: file_def = self._files[file_id] file_name = file_def['Name'] if file_def.get('Type') == 'Downloadable': cache_folder = self._download_url_file(file_def, file_id) return self._make_symlink(cache_folder, file_name, script) else: cache_path = self._fetch_file(file_id) return self._make_symlink(cache_path, file_name, script) def _make_symlink(self, cache_path, file_name, script): script_folder = os.path.join(self._cache_folder, script) if not os.path.isdir(script_folder): os.mkdir(script_folder) file_folder = os.path.join(script_folder, os.path.dirname(file_name)) if not os.path.isdir(file_folder): os.makedirs(file_folder) if cache_path is not None: script_path = os.path.join(script_folder, file_name) if not os.path.lexists(script_path): os.symlink(cache_path, script_path) return script_path def _fetch_file(self, file_id): if file_id in self._fetched_files: return self._fetched_files[file_id] filedef = self._files[file_id] out_path = os.path.join(self._cache_folder, file_id) body_type = filedef.get('BodyType', 'Text') with open(out_path, 'w') as out_file: if body_type == 'Text': out_file.write(filedef['Body']) elif body_type == 'Base64': out_file.write(util.b64decode(filedef['Body'])) self._fetched_files[file_id] = out_path return out_path def _download_url_file(self, file_def, file_id): """It download the file in the murano-agent. It can proceed from a git file or any other internal URL :param file_def: file description :param file_id: the ID file to download :param input: """ folder = os.path.join(self._cache_folder, file_id) if os.path.isdir(folder): return folder if 'URL' not in file_def: raise ValueError("No valid URL in file {0}". format(file_def)) url_file = file_def['URL'] if not self._url(url_file): raise ValueError("Provided URL is not valid {0}". format(url_file)) if not os.path.isdir(folder): os.makedirs(folder) try: if self._is_git_repository(url_file): git.Git().clone(url_file, folder) elif self._is_svn_repository(url_file): self._download_svn(url_file, folder) else: self._download_file(url_file, folder) except Exception as e: if self._is_git_repository(url_file): mns = ("Error to clone the git repository {0}: {1}". format(url_file, e.message)) else: mns = ("Error to download the file {0}: {1}". format(url_file, e.message)) LOG.warning(mns) raise ValueError(mns) return folder def clear(self): shutil.rmtree(self._cache_folder, ignore_errors=True) def _download_file(self, url, path): local_filename = url.split('/')[-1] r = requests.get(url, stream=True) with open(os.path.join(path, local_filename), 'wb') as f: for chunk in r.iter_content(chunk_size=1024): if chunk: f.write(chunk) f.flush() return local_filename def _url(self, file): return (urllib.parse.urlsplit(file).scheme or urllib.parse.urlsplit(file).netloc) def _is_git_repository(self, url): return (url.startswith(("git://", "git+http://", "git+https:/")) or url.endswith('.git')) def _is_svn_repository(self, url): http_regex = "https?://(.*)/svn/(.*)" http_matches = re.search(http_regex, url) svn_regex = "svn://(.*)" svn_matches = re.search(svn_regex, url) if http_matches is None and svn_matches is None: return False else: return True def _download_svn(self, url_file, folder): self._execute_command("svn checkout {0} --non-interactive " "--trust-server-cert {1}". format(url_file, folder)) def _execute_command(self, command): process = subprocess.Popen( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True, cwd=os.getcwd(), shell=True) stdout, stderr = process.communicate(input) retcode = process.poll() if stdout is not None: stdout = encodeutils.safe_decode('utf-8') LOG.debug(stdout) if stderr is not None: stderr = encodeutils.safe_decode('utf-8') LOG.error(stderr) if retcode != 0: raise ValueError(stderr) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/opts.py0000664000175000017500000000330100000000000020014 0ustar00zuulzuul00000000000000# Copyright (c) 2014 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import copy import itertools import muranoagent.common.config def build_list(opt_list): return list(itertools.chain(*opt_list)) # List of *all* options in [DEFAULT] namespace of murano. # Any new option list or option needs to be registered here. _opt_lists = [ ('rabbitmq', muranoagent.common.config.rabbit_opts), (None, build_list([ muranoagent.common.config.opts, ])) ] def list_opts(): """Return a list of oslo.config options available in Murano-Agent. Each element of the list is a tuple. The first element is the name of the group under which the list of elements in the second element will be registered. A group name of None corresponds to the [DEFAULT] group in config files. This function is also discoverable via the 'muranoagent' entry point under the 'oslo.config.opts' namespace. The purpose of this is to allow tools like the Oslo sample config file generator to discover the options exposed to users by Murano. :returns: a list of (group_name, opts) tuples """ return [(g, copy.deepcopy(o)) for g, o in _opt_lists] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/script_runner.py0000664000175000017500000000527000000000000021733 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import os from muranoagent import executors as exe class FunctionRunner(object): def __init__(self, name, script_runner): self._name = name self._script_executor = script_runner def __call__(self, *args, **kwargs): return self._script_executor.execute_function( self._name, *args, **kwargs) class ScriptRunner(object): def __init__(self, name, script_info, files_manager): self._name = name self._executor = self._get_executor(script_info['Type'], name, script_info['EntryPoint']) self._script_info = script_info self._script_loaded = False self._files_manager = files_manager def __call__(self, *args, **kwargs): return self.execute_function(None, *args, **kwargs) def _get_executor(self, script_type, script_name, entry_point): create_executor = exe.Executors.create_executor if script_type != 'Application': executor = create_executor(script_type, entry_point) else: executor = create_executor(script_type, script_name) if executor is None: raise ValueError('The application type in {0} is not a valid ' 'executor {1}'.format(script_name, script_type)) return executor def execute_function(self, name, *args, **kwargs): self._load() return self._executor.run(name, *args, **kwargs) def __getattr__(self, item): return FunctionRunner(item, self) def _load(self): if not self._script_loaded: self._executor.load( self._prepare_files(), self._script_info.get("Options") or {}) self._script_loaded = True def _prepare_files(self): for file_id in self._script_info.get('Files', []): self._files_manager.put_file(file_id, self._name) if self._script_info["Type"] == 'Application': return self._files_manager.put_file( self._script_info["EntryPoint"], self._name) return os.path.join(self._files_manager._cache_folder, self._name) ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2408829 murano-agent-9.0.0/muranoagent/tests/0000775000175000017500000000000000000000000017622 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/__init__.py0000664000175000017500000000000000000000000021721 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2448828 murano-agent-9.0.0/muranoagent/tests/unit/0000775000175000017500000000000000000000000020601 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/__init__.py0000664000175000017500000000000000000000000022700 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/base.py0000664000175000017500000000177300000000000022075 0ustar00zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import fixtures from oslo_config import cfg import testtools from muranoagent.common import config # noqa CONF = cfg.CONF class MuranoAgentTestCase(testtools.TestCase): def setUp(self): super(MuranoAgentTestCase, self).setUp() self.useFixture(fixtures.FakeLogger('murano-agent')) def override_config(self, name, override, group=None): CONF.set_override(name, override, group) self.addCleanup(CONF.clear_override, name, group) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/execution_plan.py0000664000175000017500000002262700000000000024201 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import fixtures from muranoagent import bunch class ExPlanDownloable(fixtures.Fixture): def setUp(self): super(ExPlanDownloable, self).setUp() self.execution_plan = bunch.Bunch( Action='Execute', Body='return deploy(args.appName).stdout\n', Files={ 'ID1': { 'Name': 'tomcat.git', 'Type': 'Downloadable', 'URL': 'https://github.com/tomcat.git' }, 'ID2': { 'Name': 'java', 'Type': 'Downloadable', 'URL': 'https://github.com/java.git' }, }, FormatVersion='2.1.0', ID='ID', Name='Deploy Chef', Parameters={ 'appName': '$appName' }, Scripts={ 'deploy': { 'EntryPoint': 'cookbook::recipe', 'Files': [ 'ID1', 'ID2' ], 'Options': { 'captureStderr': True, 'captureStdout': True }, 'Type': 'Chef', 'Version': '1.0.0' } }, Version='1.0.0' ) self.addCleanup(delattr, self, 'execution_plan') class ExPlanApplication(fixtures.Fixture): def setUp(self): super(ExPlanApplication, self).setUp() self.execution_plan = bunch.Bunch( Action='Execute', Body='return deploy(args.appName).stdout', Files={ 'ID1': { 'Body': 'text', 'BodyType': 'Text', 'Name': 'deployTomcat.sh' }, 'ID2': { 'Body': 'dGV4dA==\n', 'BodyType': 'Base64', 'Name': 'installer' }, 'ID3': { 'Body': 'dGV4dA==\n', 'BodyType': 'Base64', 'Name': 'common.sh' } }, FormatVersion='2.1.0', ID='ID', Name='Deploy Tomcat', Parameters={ 'appName': '$appName' }, Scripts={ 'deploy': { 'EntryPoint': 'ID1', 'Files': [ 'ID2', 'ID3' ], 'Options': { 'captureStderr': True, 'captureStdout': True }, 'Type': 'Application', 'Version': '1.0.0' } }, Version='1.0.0' ) self.addCleanup(delattr, self, 'execution_plan') class ExPlanDownloableWrongFormat(fixtures.Fixture): def setUp(self): super(ExPlanDownloableWrongFormat, self).setUp() self.execution_plan = bunch.Bunch( ID='ID', FormatVersion='0.0.0' ) self.addCleanup(delattr, self, 'execution_plan') class ExPlanDownloableNoFiles(fixtures.Fixture): def setUp(self): super(ExPlanDownloableNoFiles, self).setUp() self.execution_plan = bunch.Bunch( ID='ID', FormatVersion='2.1.0', Scripts={ 'deploy': { 'EntryPoint': 'cookbook::recipe', 'Files': [ 'https://github.com/tomcat.git', {'java': 'https://github.com/java.git'} ], 'Options': { 'captureStderr': True, 'captureStdout': True }, 'Type': 'Chef', 'Version': '1.0.0' } } ) self.addCleanup(delattr, self, 'execution_plan') class PuppetExPlanDownloable(fixtures.Fixture): def setUp(self): super(PuppetExPlanDownloable, self).setUp() self.execution_plan = bunch.Bunch( Action='Execute', Body='return deploy(args.appName).stdout\n', Files={ 'ID1': { 'Name': 'tomcat.git', 'Type': 'Downloadable', 'URL': 'https://github.com/tomcat.git' }, 'ID2': { 'Name': 'java', 'Type': 'Downloadable', 'URL': 'https://github.com/java.git' }, }, FormatVersion='2.0.0', ID='ID', Name='Deploy Puppet', Parameters={ 'appName': '$appName' }, Scripts={ 'deploy': { 'EntryPoint': 'cookbook::recipe', 'Files': [ 'ID1', 'ID2' ], 'Options': { 'captureStderr': True, 'captureStdout': True }, 'Type': 'Puppet', 'Version': '1.0.0' } }, Version='1.0.0' ) self.addCleanup(delattr, self, 'execution_plan') class ExPlanBerkshelf(fixtures.Fixture): def setUp(self): super(ExPlanBerkshelf, self).setUp() self.execution_plan = bunch.Bunch( Action='Execute', Body='return deploy(args.appName).stdout\n', Files={ 'ID1': { 'Name': 'tomcat.git', 'Type': 'Downloadable', 'URL': 'https://github.com/tomcat.git' } }, FormatVersion='2.2.0', ID='ID', Name='Deploy Chef', Parameters={}, Scripts={ 'deploy': { 'EntryPoint': 'cookbook::recipe', 'Files': [ 'ID1' ], 'Options': { 'captureStderr': True, 'captureStdout': True, 'useBerkshelf': True }, 'Type': 'Chef', 'Version': '1.0.0' } }, Version='1.0.0' ) self.addCleanup(delattr, self, 'execution_plan') class ExPlanCustomBerskfile(fixtures.Fixture): def setUp(self): super(ExPlanCustomBerskfile, self).setUp() self.execution_plan = bunch.Bunch( Action='Execute', Body='return deploy(args.appName).stdout\n', Files={ 'ID1': { 'Name': 'tomcat.git', 'Type': 'Downloadable', 'URL': 'https://github.com/tomcat.git' } }, FormatVersion='2.2.0', ID='ID', Name='Deploy Chef', Parameters={}, Scripts={ 'deploy': { 'EntryPoint': 'cookbook::recipe', 'Files': [ 'ID1' ], 'Options': { 'captureStderr': True, 'captureStdout': True, 'useBerkshelf': True, 'berksfilePath': 'custom/customFile' }, 'Type': 'Chef', 'Version': '1.0.0' } }, Version='1.0.0' ) self.addCleanup(delattr, self, 'execution_plan') class ExPlanBerkWrongVersion(fixtures.Fixture): def setUp(self): super(ExPlanBerkWrongVersion, self).setUp() self.execution_plan = bunch.Bunch( Action='Execute', Body='return deploy(args.appName).stdout\n', Files={ 'ID1': { 'Name': 'tomcat.git', 'Type': 'Downloadable', 'URL': 'https://github.com/tomcat.git' } }, FormatVersion='2.1.0', ID='ID', Name='Deploy Chef', Parameters={}, Scripts={ 'deploy': { 'EntryPoint': 'cookbook::recipe', 'Files': [ 'ID1' ], 'Options': { 'captureStderr': True, 'captureStdout': True, 'useBerkshelf': True }, 'Type': 'Chef', 'Version': '1.0.0' } }, Version='1.0.0' ) self.addCleanup(delattr, self, 'execution_plan') ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2448828 murano-agent-9.0.0/muranoagent/tests/unit/executors/0000775000175000017500000000000000000000000022622 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/executors/__init__.py0000664000175000017500000000000000000000000024721 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/executors/test_chef.py0000664000175000017500000002375300000000000025152 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import fixtures import json import os from unittest import mock from unittest.mock import ANY from muranoagent import bunch from muranoagent import exceptions as ex from muranoagent.executors import chef from muranoagent.tests.unit import base from muranoagent.tests.unit import execution_plan as ep class TestChefExecutor(base.MuranoAgentTestCase, fixtures.TestWithFixtures): def setUp(self): super(TestChefExecutor, self).setUp() self.chef_executor = chef.ChefExecutor('cookbook::recipe') def test_create_nodejson_noatts(self): """It tests the manifest without attributes.""" node = self.chef_executor._create_manifest('cookbook', 'recipe', None) self.assertEqual(json.loads(node), self.get_node_no_atts()) def test_create_nodejson(self): """It tests a manifest with attributes.""" atts = { 'att1': 'value1', 'att2': 'value2' } node = self.chef_executor._create_manifest('cookbook', 'recipe', atts) self.assertEqual(json.loads(node), self.get_node_atts()) @mock.patch('subprocess.Popen') @mock.patch('builtins.open') @mock.patch('os.path.exists') @mock.patch('os.path.isdir') def test_cookbook(self, mock_isdir, mock_exist, open_mock, mock_subproc_popen): """It tests chef executor.""" self._open_mock(open_mock) mock_exist.return_value = True mock_isdir.return_value = True process_mock = mock.Mock() attrs = {'communicate.return_value': ('output', 'ok'), 'poll.return_value': 0} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.ExPlanDownloable()).execution_plan script = list(template['Scripts'].values()) self.chef_executor.load('path', script[0]['Options']) self.chef_executor.run('test') @mock.patch('subprocess.Popen') @mock.patch('builtins.open') @mock.patch('os.path.exists') @mock.patch('os.path.isdir') def test_cookbook_error(self, mock_isdir, mock_exist, open_mock, mock_subproc_popen): """It tests chef executor with error in the request.""" self._open_mock(open_mock) mock_exist.return_value = True mock_isdir.return_value = True process_mock = mock.Mock() attrs = {'communicate.return_value': ('output', 'error'), 'poll.return_value': 2} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.ExPlanDownloable()).execution_plan script = list(template['Scripts'].values())[0] self.chef_executor.load('path', script['Options']) self.assertRaises(ex.CustomException, self.chef_executor.run, 'test') def test_chef_cookbook_wrong(self): """It tests a wrong cookbook name.""" chef_executor = chef.ChefExecutor('wrong') self.assertRaises(ex.CustomException, chef_executor.run, 'test') def test_chef_no_berkshelf(self): """It tests the cookbook path if Berkshelf is not enabled""" template = self.useFixture(ep.ExPlanDownloable()).execution_plan script = list(template['Scripts'].values())[0] self.chef_executor.load('path', script['Options']) cookbook_path = self.chef_executor._create_cookbook_path('cookbook') self.assertEqual(cookbook_path, os.path.abspath('path')) @mock.patch('subprocess.Popen') @mock.patch('os.path.isfile') def test_chef_berkshelf_default_berksfile(self, mock_isfile, mock_subproc_popen): """It tests Berkshelf usage if no Berksfile path is provided""" mock_isfile.return_value = True process_mock = mock.Mock() attrs = {'communicate.return_value': ('output', 'ok'), 'poll.return_value': 0} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.ExPlanBerkshelf()).execution_plan script = list(template['Scripts'].values())[0] self.chef_executor.load('path', script['Options']) self.chef_executor.module_name = 'test' cookbook_path = self.chef_executor._create_cookbook_path('cookbook') self.assertEqual(cookbook_path, os.path.abspath('path/berks-cookbooks')) expected_command = 'berks vendor --berksfile={0} {1}'.format( os.path.abspath('path/cookbook/Berksfile'), cookbook_path) mock_subproc_popen.assert_called_once_with(expected_command, cwd=ANY, shell=ANY, stdout=ANY, stderr=ANY, universal_newlines=ANY) @mock.patch('subprocess.Popen') @mock.patch('os.path.isfile') def test_chef_berkshelf_custom_berksfile(self, mock_isfile, mock_subproc_popen): """It tests Berkshelf usage if a custom Berksfile is provided""" mock_isfile.return_value = True process_mock = mock.Mock() attrs = {'communicate.return_value': ('output', 'ok'), 'poll.return_value': 0} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.ExPlanCustomBerskfile()).execution_plan script = list(template['Scripts'].values())[0] self.chef_executor.load('path', script['Options']) self.chef_executor.module_name = 'test' cookbook_path = self.chef_executor._create_cookbook_path('cookbook') self.assertEqual(cookbook_path, os.path.abspath('path/berks-cookbooks')) expected_command = 'berks vendor --berksfile={0} {1}'.format( os.path.abspath('path/custom/customFile'), cookbook_path) mock_subproc_popen.assert_called_once_with(expected_command, cwd=ANY, shell=ANY, stdout=ANY, stderr=ANY, universal_newlines=ANY) @mock.patch('subprocess.Popen') @mock.patch('os.path.isfile') def test_chef_berkshelf_error(self, mock_isfile, mock_subproc_popen): """It tests if Berkshelf throws an error""" mock_isfile.return_value = True process_mock = mock.Mock() attrs = {'communicate.return_value': ('output', 'error'), 'poll.return_value': 2} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.ExPlanBerkshelf()).execution_plan script = list(template['Scripts'].values())[0] self.chef_executor.load('path', script['Options']) self.chef_executor.module_name = 'test' self.assertRaises(ex.CustomException, self.chef_executor._create_cookbook_path, 'cookbook') def _open_mock(self, open_mock): context_manager_mock = mock.Mock() open_mock.return_value = context_manager_mock file_mock = mock.Mock() file_mock.read.return_value = '' enter_mock = mock.Mock() enter_mock.return_value = file_mock exit_mock = mock.Mock() setattr(context_manager_mock, '__enter__', enter_mock) setattr(context_manager_mock, '__exit__', exit_mock) def _stub_uuid(self, values=None): class FakeUUID(object): def __init__(self, v): self.hex = v if values is None: values = [] mock_uuid4 = mock.patch('uuid.uuid4').start() mock_uuid4.side_effect = [FakeUUID(v) for v in values] return mock_uuid4 def get_template_downloable(self): return bunch.Bunch( ID='ID', Files={ 'file': { 'Name': 'myfile', 'URL': 'https://github.com' '/apache/tomcat/blob/trunk/LICENSE', 'Type': 'Downloadable' } } ) def get_template_file(self): return bunch.Bunch( ID='ID', Files={ 'test': { 'Body': 'dGV4dA==\n', 'BodyType': 'Base64', 'Name': 'installer' } } ) def get_node_atts(self): return { "run_list": [ "recipe[cookbook::recipe]" ], "cookbook": { "att1": "value1", "att2": "value2" } } def get_node_no_atts(self): return { "run_list": [ "recipe[cookbook::recipe]" ] } ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/executors/test_puppet.py0000664000175000017500000001160000000000000025546 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from unittest import mock import fixtures from muranoagent import bunch from muranoagent import exceptions as ex from muranoagent.executors import puppet from muranoagent.tests.unit import base from muranoagent.tests.unit import execution_plan as ep class TestPuppetExecutor(base.MuranoAgentTestCase, fixtures.TestWithFixtures): def setUp(self): super(TestPuppetExecutor, self).setUp() self.puppet_executor = puppet.PuppetExecutor('module::recipe') def test_create_manifest(self): node = self.puppet_executor._create_manifest('cookbook', 'recipe') self.assertEqual(node, self.get_manifest('cookbook', 'recipe')) def test_create_manifest_norecipe(self): node = self.puppet_executor._create_manifest('cookbook', '') self.assertEqual(node, self.get_manifest_norecipe('cookbook')) def test_create_hierdata(self): atts = { 'att1': 'value1', 'att2': 'value2' } node = self.puppet_executor._create_hiera_data('cookbook', atts) self.assertEqual(node, self.get_hieradata()) @mock.patch('builtins.open') def test_generate_files(self, open_mock): self._open_mock(open_mock) atts = { 'att1': 'value1', 'att2': 'value2' } self.puppet_executor._generate_files('cookbook', 'recipe', atts) @mock.patch('builtins.open') def test_configure_puppet(self, open_mock): self._open_mock(open_mock) self.puppet_executor._configure_puppet() @mock.patch('subprocess.Popen') @mock.patch('builtins.open') def test_module(self, open_mock, mock_subproc_popen): # # setup # self._open_mock(open_mock) process_mock = mock.Mock() attrs = {'communicate.return_value': ('ouput', 'ok'), 'poll.return_value': 0} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.PuppetExPlanDownloable()).execution_plan script = list(template['Scripts'].values())[0] self.puppet_executor.load('path', script['Options']) self.puppet_executor.run('test') @mock.patch('subprocess.Popen') @mock.patch('builtins.open') def test_module_error(self, open_mock, mock_subproc_popen): # # setup # self._open_mock(open_mock) process_mock = mock.Mock() attrs = {'communicate.return_value': ('ouput', 'error'), 'poll.return_value': 2} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.useFixture(ep.PuppetExPlanDownloable()).execution_plan script = list(template['Scripts'].values())[0] self.puppet_executor.load('path', script['Options']) self.assertRaises(ex.CustomException, self.puppet_executor.run, 'test') def test_puppet_module_wrong(self): puppet_executor = puppet.PuppetExecutor('wrong') self.assertRaises(ex.CustomException, puppet_executor.run, 'test') def _stub_uuid(self, values=None): class FakeUUID(object): def __init__(self, v): self.hex = v if values is None: values = [] mock_uuid4 = mock.patch('uuid.uuid4').start() mock_uuid4.side_effect = [FakeUUID(v) for v in values] return mock_uuid4 def _open_mock(self, open_mock): context_manager_mock = mock.Mock() open_mock.return_value = context_manager_mock file_mock = mock.Mock() file_mock.read.return_value = '' enter_mock = mock.Mock() enter_mock.return_value = file_mock exit_mock = mock.Mock() setattr(context_manager_mock, '__enter__', enter_mock) setattr(context_manager_mock, '__exit__', exit_mock) def get_hieradata(self): return {'cookbook::att1': 'value1', 'cookbook::att2': 'value2'} def get_manifest(self, cookbook, recipe): return "node \'default\' { " \ "class { " + cookbook + '::' + recipe + ':}}' def get_manifest_norecipe(self, cookbook): return "node \'default\' { " \ "class { " + cookbook + ':}}' ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/test_agent.py0000664000175000017500000000121100000000000023303 0ustar00zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import testtools class MuranoAgentTest(testtools.TestCase): def test_nothing(self): pass ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/test_app.py0000664000175000017500000001422000000000000022771 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from unittest import mock import fixtures import ssl as ssl_module from muranoagent import app from muranoagent import bunch from muranoagent.common import config as cfg from muranoagent.common.messaging import mqclient from muranoagent import exceptions as exc from muranoagent.tests.unit import base from muranoagent.tests.unit import execution_plan as ep from muranoagent import validation CONF = cfg.CONF class TestApp(base.MuranoAgentTestCase, fixtures.FunctionFixture): @mock.patch('os.chmod') @mock.patch('os.path.exists') def setUp(self, mock_path, mock_chmod): super(TestApp, self).setUp() mock_path.side_effect = self._exists self.agent = app.MuranoAgent() CONF.set_override('storage', 'cache') self.addCleanup(CONF.clear_override, 'storage') @staticmethod def _exists(path): return 'stamp' not in path def test_verify_execution_plan_downloable(self): template = self.useFixture(ep.ExPlanDownloable()).execution_plan self.agent._verify_plan(template) def test_verify_execution_plan_wrong_format(self): template = bunch.Bunch( ID='ID', FormatVersion='0.0.0', ) self.assertRaises(exc.IncorrectFormat, validation.validate_plan, template) def test_verify_over_max_execution_plan(self): template = self.useFixture(ep.ExPlanApplication()).execution_plan template['FormatVersion'] = '1000.0.0' self.assertRaises(exc.IncorrectFormat, validation.validate_plan, template) def test_verify_execution_application(self): template = self.useFixture(ep.ExPlanApplication()).execution_plan self.agent._verify_plan(template) def test_verify_wrong_execution_application(self): template = self.useFixture(ep.ExPlanApplication()).execution_plan template['Files']['ID1'] = { 'Name': 'tomcat.git', 'Type': 'Downloadable', 'URL': 'https://github.com/tomcat.git' } template['FormatVersion'] = '2.0.0' self.assertRaises(exc.IncorrectFormat, validation.validate_plan, template) def test_verify_execution_plan_no_files(self): template = self.useFixture(ep.ExPlanDownloableNoFiles()).execution_plan self.assertRaises(exc.IncorrectFormat, validation.validate_plan, template) def test_verify_execution_plan_berkshelf(self): template = self.useFixture(ep.ExPlanBerkshelf()).execution_plan self.agent._verify_plan(template) def test_verify_execution_plan_berkshelf_wrong_version(self): template = self.useFixture(ep.ExPlanBerkWrongVersion()).execution_plan self.assertRaises(exc.IncorrectFormat, validation.validate_plan, template) @mock.patch.object(mqclient, 'random', autospec=True) @mock.patch.object(mqclient, 'kombu', autospec=True) def test_rmq_client_initialization_with_ssl_version(self, mock_kombu, mock_random): expected_heartbeat = 20 # 20 = 20 + 20 * 0, due to mocked value below. mock_random.random.return_value = 0 ssl_versions = ( ('tlsv1', getattr(ssl_module, 'PROTOCOL_TLSv1', None)), ('tlsv1_1', getattr(ssl_module, 'PROTOCOL_TLSv1_1', None)), ('tlsv1_2', getattr(ssl_module, 'PROTOCOL_TLSv1_2', None)), ('sslv2', getattr(ssl_module, 'PROTOCOL_SSLv2', None)), ('sslv23', getattr(ssl_module, 'PROTOCOL_SSLv23', None)), ('sslv3', getattr(ssl_module, 'PROTOCOL_SSLv3', None))) exception_count = 0 for ssl_name, ssl_version in ssl_versions: ssl_kwargs = { 'login': 'test_login', 'password': 'test_password', 'host': 'test_host', 'port': 'test_port', 'virtual_host': 'test_virtual_host', 'ssl': True, 'ssl_version': ssl_name, 'ca_certs': ['cert1'], 'insecure': False } # If a ssl_version is not valid, a RuntimeError is thrown. # According to the ssl_version docs in config.py, certain versions # of TLS may be available depending on the system. So, just # check that at least 1 ssl_version works. if ssl_version is None: e = self.assertRaises(RuntimeError, mqclient.MqClient, **ssl_kwargs) self.assertEqual('Invalid SSL version: %s' % ssl_name, e.__str__()) exception_count += 1 continue self.ssl_client = mqclient.MqClient(**ssl_kwargs) mock_kombu.Connection.assert_called_once_with( 'amqp://{0}:{1}@{2}:{3}/{4}'.format( 'test_login', 'test_password', 'test_host', 'test_port', 'test_virtual_host'), heartbeat=expected_heartbeat, ssl={'ca_certs': ['cert1'], 'cert_reqs': ssl_module.CERT_REQUIRED, 'ssl_version': ssl_version}) self.assertEqual( mock_kombu.Connection(), self.ssl_client._connection) self.assertIsNone(self.ssl_client._channel) self.assertFalse(self.ssl_client._connected) mock_kombu.Connection.reset_mock() # Check that at least one ssl_version worked. self.assertGreater(len(ssl_versions), exception_count) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/test_execution_plan_queue.py0000664000175000017500000000467400000000000026446 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from unittest import mock import builtins import fixtures from muranoagent import execution_plan_queue from muranoagent import app from muranoagent import bunch from muranoagent.common import config as cfg from muranoagent.common.messaging import mqclient from muranoagent import exceptions as exc from muranoagent.tests.unit import base from muranoagent.tests.unit import execution_plan as ep from muranoagent import validation CONF = cfg.CONF class TestExecutionPlanQueue(base.MuranoAgentTestCase, fixtures.FunctionFixture): @mock.patch('os.chmod') @mock.patch('os.path.exists') def setUp(self, mock_path, mock_chmod): super(TestExecutionPlanQueue, self).setUp() mock_path.side_effect = self._exists self.epq = execution_plan_queue.ExecutionPlanQueue() CONF.set_override('storage', 'cache') self.addCleanup(CONF.clear_override, 'storage') @staticmethod def _exists(path): return 'stamp' not in path @mock.patch('os.path.lexists') @mock.patch('os.path.isdir') @mock.patch('os.mkdir') def test_put_execution_plan(self, mock_makedir, mock_path, mock_exists): mock_path.return_value = True mock_makedir.return_value = None mock_exists.return_value = True mock_write = mock.mock_open() execution_plan = 'myplan' signature = None msg_id = 1 reply_to = 'test' expected_content = ('{"Data": "bXlwbGFu", "Signature": "", ' '"ID": 1, "ReplyTo": "test"}') with mock.patch.object(builtins, 'open', mock_write) as mocked_file: self.epq.put_execution_plan(execution_plan, signature, msg_id, reply_to) mocked_file().write.assert_called_once_with(expected_content) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/test_files_manager.py0000664000175000017500000001747300000000000025022 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import os.path from unittest import mock from muranoagent import bunch from muranoagent.common import config as cfg from muranoagent import files_manager from muranoagent.tests.unit import base CONF = cfg.CONF class TestFileManager(base.MuranoAgentTestCase): @mock.patch('os.path.isdir') @mock.patch('os.mkdir') @mock.patch('os.makedirs') def setUp(self, mock_makedir, mock_mkdir, mock_path): mock_path.return_value = True mock_mkdir.return_value = None mock_makedir.return_value = None super(TestFileManager, self).setUp() CONF.set_override('storage', 'cache') def test_is_svn(self): files = files_manager.FilesManager(self.get_template_downloable(1)) self.assertTrue(files._is_svn_repository("https://sdfa/svn/ss")) def test_is_svn_first(self): files = files_manager.FilesManager(self.get_template_downloable(2)) self.assertTrue(files._is_svn_repository("svn://test")) def test_is_svn_wrong_http_protocol(self): files = files_manager.FilesManager(self.get_template_downloable(3)) self.assertFalse(files._is_svn_repository("httpp://sdfa/svn/ss")) def test_is_svn_wrong_svn_slash(self): files = files_manager.FilesManager(self.get_template_downloable(4)) self.assertFalse(files._is_svn_repository("svn:sdfa/svn/ss")) @mock.patch("git.Git") @mock.patch('os.path.isdir') @mock.patch('os.makedirs') def test_execution_plan_type_downloable_git(self, mock_makedir, mock_path, mock_git): """Test an execution plan with downloadable git files """ mock_makedir.return_value = None mock_path.return_value = True mock_git.clone.return_value = None template = self.get_template_downloable_git() files = files_manager.FilesManager(self.get_template_downloable(5)) files._download_url_file(template.Files['mycoockbook'], "script") @mock.patch('os.path.isdir') @mock.patch('os.mkdir') @mock.patch('os.makedirs') @mock.patch('builtins.open') @mock.patch('requests.get') def test_execution_plan_type_downloable(self, mock_requests, open_mock, mock_makedir, mock_mkdir, mock_path): """Test an execution plan with downloadable files """ mock_path.return_value = True mock_mkdir.return_value = None mock_makedir.return_value = None mock_requests.return_value = None self._open_mock(open_mock) template = self.get_template_downloable(6) files = files_manager.FilesManager(self.get_template_downloable(6)) files._download_url_file(template.Files['file'], "script") @mock.patch('subprocess.Popen') @mock.patch('os.makedirs') def test_execution_plan_type_svn(self, mock_makedir, mock_subproc_popen): """Test an execution plan with svn files.""" process_mock = mock.Mock() attrs = {'communicate.return_value': ('ouput', 'ok'), 'poll.return_value': 0} process_mock.configure_mock(**attrs) mock_subproc_popen.return_value = process_mock template = self.get_template_svn() files = files_manager.FilesManager(template) files._download_url_file(template.Files['file'], "script") @mock.patch('os.makedirs') def test_execution_plan_type_downloable_no_Url(self, mock_makedir): """It validates the URL.""" mock_makedir.return_value = None template = bunch.Bunch( ID='ID', Files={ 'mycoockbook': { 'Name': 'mycoockbook.txt', 'Type': 'Downloadable' } } ) files = files_manager.FilesManager(template) self.assertRaises(ValueError, files._download_url_file, template.Files['mycoockbook'], "script") @mock.patch("git.Git") @mock.patch('os.path.isdir') @mock.patch('os.makedirs') @mock.patch('os.path.lexists') def test_putfile_downloable(self, mock_exists, mock_makedir, path, mock_git): """It tests the putfile method when the file is a git URL. """ path.return_value = True mock_git.clone.return_value = None mock_makedir.return_value = None mock_exists.return_value = True template = self.get_template_downloable_git() files = files_manager.FilesManager(template) for file in template.get('Files'): files.put_file(file, 'deploy') @mock.patch('builtins.open') @mock.patch('os.path.lexists') @mock.patch('os.path.isdir') @mock.patch('os.makedirs') def test_putfile_file(self, mock_makedir, mock_path, mock_exists, open_mock): """It tests the putfile method.""" mock_path.return_value = True mock_makedir.return_value = None mock_exists.return_value = True context_manager_mock = mock.Mock() open_mock.return_value = context_manager_mock file_mock = mock.Mock() file_mock.read.return_value = '' enter_mock = mock.Mock() enter_mock.return_value = file_mock exit_mock = mock.Mock() setattr(context_manager_mock, '__enter__', enter_mock) setattr(context_manager_mock, '__exit__', exit_mock) template = self.get_template_file() files = files_manager.FilesManager(template) for file in template.get('Files'): files.put_file(file, 'deploy') def get_template_downloable_git(self): return bunch.Bunch( ID='ID', Files={ 'mycoockbook': { 'Name': 'mycoockbook.txt', 'URL': 'git://github.com/tomcat.git', 'Type': 'Downloadable' } } ) def get_template_downloable(self, file_id): return bunch.Bunch( ID='ID', Files={ 'file': { 'Name': 'myfile', 'URL': 'https://www.apache.org/licenses', 'Type': 'Downloadable' } } ) def get_template_svn(self): return bunch.Bunch( ID='ID', Files={ 'file': { 'Name': 'svn', 'URL': 'https://mysvn/svn/repo', 'Type': 'Downloadable' } } ) def get_template_file(self): return bunch.Bunch( ID='ID', Files={ 'test': { 'Body': 'dGV4dA==\n', 'BodyType': 'Base64', 'Name': 'installer' } } ) def _open_mock(self, open_mock): context_manager_mock = mock.Mock() open_mock.return_value = context_manager_mock file_mock = mock.Mock() file_mock.read.return_value = '' enter_mock = mock.Mock() enter_mock.return_value = file_mock exit_mock = mock.Mock() setattr(context_manager_mock, '__enter__', enter_mock) setattr(context_manager_mock, '__exit__', exit_mock) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/test_script_runner.py0000664000175000017500000000700700000000000025113 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import git from unittest import mock from muranoagent import bunch from muranoagent.common import config as cfg from muranoagent import files_manager as fmanager from muranoagent import script_runner from muranoagent.tests.unit import base CONF = cfg.CONF class TestScriptRunner(base.MuranoAgentTestCase): def setUp(self): super(TestScriptRunner, self).setUp() CONF.set_override('storage', 'ss') @mock.patch('os.path.join') @mock.patch("muranoagent.files_manager.FilesManager") @mock.patch("muranoagent.executors.Executors") def test_script_runner_downloable(self, mock_file_manager, mock_executors, mock_os): mock_file_manager.put_file.return_value = None mock_executors.create_executor.return_value = None mock_os.return_value = '/tmp/1234' template = self.get_template_downloable_git() scripts = script_runner\ .ScriptRunner('deploy', template.get('Scripts')['deploy'], mock_file_manager) scripts._prepare_files() def _stub_uuid(self, values=None): class FakeUUID(object): def __init__(self, v): self.hex = v if values is None: values = [] mock_uuid4 = mock.patch('uuid.uuid4').start() mock_uuid4.side_effect = [FakeUUID(v) for v in values] return mock_uuid4 def get_template_downloable_git(self): return bunch.Bunch( ID='ID', Files={ 'mycoockbook': { 'Name': 'mycoockbook.txt', 'URL': 'https://github.com/tomcat.git', 'Type': 'Downloadable' } }, Scripts={ 'deploy': { 'EntryPoint': 'cookbook/recipe', 'Files': [ 'https://github.com/tomcat.git', {'java': 'https://github.com/java.git'} ], 'Options': { 'captureStderr': True, 'captureStdout': True }, 'Type': 'Chef', 'Version': '1.0.0' } } ) def get_template_downloable(self): return bunch.Bunch( ID='ID', Files={ 'file': { 'Name': 'myfile', 'URL': 'https://github.com' '/apache/tomcat/blob/trunk/LICENSE', 'Type': 'Downloadable' } } ) def get_template_file(self): return bunch.Bunch( ID='ID', Files={ 'test': { 'Body': 'dGV4dA==\n', 'BodyType': 'Base64', 'Name': 'installer' } } ) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/tests/unit/test_util.py0000664000175000017500000000246400000000000023175 0ustar00zuulzuul00000000000000# Copyright (c) 2015 Telefonica I+D # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. from unittest import mock from muranoagent.tests.unit import base from muranoagent import util class TestUtils(base.MuranoAgentTestCase): def test_str_to_bytes(self): self.assertEqual(util._to_bytes('test'), b'test') def test_bytes_to_bytes(self): self.assertEqual(util._to_bytes(b'test'), b'test') def test_b64encode_str(self): self.assertEqual(util.b64encode('test'), 'dGVzdA==') def test_b64encode_bytes(self): self.assertEqual(util.b64encode(b'test'), 'dGVzdA==') def test_b64decode_str(self): self.assertEqual(util.b64decode('dGVzdA=='), 'test') def test_b64decode_bytes(self): self.assertEqual(util.b64decode(b'dGVzdA=='), 'test') ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/util.py0000664000175000017500000000231000000000000020003 0ustar00zuulzuul00000000000000# Copyright (c) 2014 Mirantis, Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import base64 def _to_bytes(string): """Coerce a string into bytes Since Python 3 now handles bytes and str differently, this helper will coerce a string to bytes if possible for use with base64 """ try: string = string.encode() except AttributeError: pass return string def b64encode(string): """Base64 encode a string to a string""" string = _to_bytes(string) return base64.b64encode(string).decode() def b64decode(string): """Base64 decode a string to a string""" string = _to_bytes(string) return base64.b64decode(string).decode() ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/validation.py0000664000175000017500000001307600000000000021173 0ustar00zuulzuul00000000000000# Copyright (c) 2017 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import semantic_version from muranoagent import exceptions as exc max_format_version = semantic_version.Spec('<=2.2.0') def validate_plan(plan): plan_format_version = semantic_version.Version( plan.get('FormatVersion', '1.0.0')) if plan_format_version not in max_format_version: # NOTE(kazitsev) this is Version in Spec not str in str raise exc.IncorrectFormat( 9, "Unsupported format version {0} " "(I support versions {1})".format( plan_format_version, max_format_version)) for attr in ('Scripts', 'Files'): if attr not in plan: raise exc.IncorrectFormat( 2, '{0} is not in the execution plan'.format(attr)) for attr in ('Scripts', 'Files', 'Options'): if attr in plan and not isinstance( plan[attr], dict): raise exc.IncorrectFormat( 2, '{0} is not a dictionary'.format(attr)) for name, script in plan.get('Scripts', {}).items(): _validate_script(name, script, plan_format_version, plan) for key, plan_file in plan.get('Files', {}).items(): _validate_file(plan_file, key, plan_format_version) def _validate_script(name, script, plan_format_version, plan): for attr in ('Type', 'EntryPoint'): if attr not in script or not isinstance(script[attr], str): raise exc.IncorrectFormat( 2, 'Incorrect {0} entry in script {1}'.format( attr, name)) if plan_format_version in semantic_version.Spec('>=2.0.0,<2.1.0'): if script['Type'] != 'Application': raise exc.IncorrectFormat( 2, 'Type {0} is not valid for format {1}'.format( script['Type'], plan_format_version)) if script['EntryPoint'] not in plan.get('Files', {}): raise exc.IncorrectFormat( 2, 'Script {0} misses entry point {1}'.format( name, script['EntryPoint'])) if plan_format_version in semantic_version.Spec('>=2.1.0'): if script['Type'] not in ('Application', 'Chef', 'Puppet'): raise exc.IncorrectFormat( 2, 'Script has not a valid type {0}'.format( script['Type'])) if (script['Type'] == 'Application' and script['EntryPoint'] not in plan.get('Files', {})): raise exc.IncorrectFormat( 2, 'Script {0} misses entry point {1}'.format( name, script['EntryPoint'])) elif (script['Type'] != 'Application' and "::" not in script['EntryPoint']): raise exc.IncorrectFormat( 2, 'Wrong EntryPoint {0} for Puppet/Chef ' 'executors. :: needed'.format(script['EntryPoint'])) for option in script['Options']: if option in ('useBerkshelf', 'berksfilePath'): if plan_format_version in semantic_version.Spec('<2.2.0'): raise exc.IncorrectFormat( 2, 'Script has an option {0} invalid ' 'for version {1}'.format(option, plan_format_version)) elif script['Type'] != 'Chef': raise exc.IncorrectFormat( 2, 'Script has an option {0} invalid ' 'for type {1}'.format(option, script['Type'])) for additional_file in script.get('Files', []): mns_error = ('Script {0} misses file {1}'.format( name, additional_file)) if isinstance(additional_file, dict): if (list(additional_file.keys())[0] not in plan.get('Files', {}).keys()): raise exc.IncorrectFormat(2, mns_error) elif additional_file not in plan.get('Files', {}): raise exc.IncorrectFormat(2, mns_error) def _validate_file(plan_file, key, format_version): if format_version in semantic_version.Spec('>=2.0.0,<2.1.0'): for plan in plan_file.keys(): if plan in ('Type', 'URL'): raise exc.IncorrectFormat( 2, 'Download file is {0} not valid for this ' 'version {1}'.format(key, format_version)) if 'Type' in plan_file: for attr in ('Type', 'URL', 'Name'): if attr not in plan_file: raise exc.IncorrectFormat( 2, 'Incorrect {0} entry in file {1}'.format(attr, key)) elif 'Body' in plan_file: for attr in ('BodyType', 'Body', 'Name'): if attr not in plan_file: raise exc.IncorrectFormat( 2, 'Incorrect {0} entry in file {1}'.format( attr, key)) if plan_file['BodyType'] not in ('Text', 'Base64'): raise exc.IncorrectFormat( 2, 'Incorrect BodyType in file {0}'.format(key)) else: raise exc.IncorrectFormat( 2, 'Invalid file {0}: {1}'.format( key, plan_file)) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/version.py0000664000175000017500000000121100000000000020512 0ustar00zuulzuul00000000000000# Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import pbr.version version_info = pbr.version.VersionInfo('murano-agent') ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/muranoagent/win32.py0000664000175000017500000000151600000000000017777 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Mirantis Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. try: import os import win32file def symlink(source, link_name): src = os.path.abspath(source) dest = os.path.abspath(link_name) win32file.CreateSymbolicLink(dest, src, 0) os.symlink = symlink except ImportError: pass ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2248828 murano-agent-9.0.0/releasenotes/0000775000175000017500000000000000000000000016631 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2448828 murano-agent-9.0.0/releasenotes/notes/0000775000175000017500000000000000000000000017761 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/notes/.placeholder0000664000175000017500000000000000000000000022232 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/notes/drop-py-2-7-33ea9091c6530815.yaml0000664000175000017500000000032600000000000024536 0ustar00zuulzuul00000000000000--- upgrade: - | Python 2.7 support has been dropped. Last release of murano-agent to support python 2.7 is OpenStack Train. The minimum version of Python now supported by murano-agent is Python 3.6. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/notes/fix-1591614-1b2db4cbb41f411c.yaml0000664000175000017500000000020100000000000024603 0ustar00zuulzuul00000000000000--- fixes: - Fixed too many arguments provided for format exception message for wrong entrypoint in Puppet/Chef executors. ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/notes/install-chef-d67f115c0958c116.yaml0000664000175000017500000000022400000000000025273 0ustar00zuulzuul00000000000000--- fixes: - Elements were updated to allow building murano fedora images with chef installed. Chef is installed from https://packages.chef.io././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/notes/python3-54ba2f6e70795ba6.yaml0000664000175000017500000000007300000000000024472 0ustar00zuulzuul00000000000000--- prelude: > murano-agent has been ported to python3 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/notes/python3-base64-usage-aeef2270be7bdf26.yaml0000664000175000017500000000011500000000000027065 0ustar00zuulzuul00000000000000--- fixes: - Fixed a string handling issue with base64 when using Python 3 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2488828 murano-agent-9.0.0/releasenotes/source/0000775000175000017500000000000000000000000020131 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2488828 murano-agent-9.0.0/releasenotes/source/_static/0000775000175000017500000000000000000000000021557 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/_static/.placeholder0000664000175000017500000000000000000000000024030 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2488828 murano-agent-9.0.0/releasenotes/source/_templates/0000775000175000017500000000000000000000000022266 5ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/_templates/.placeholder0000664000175000017500000000000000000000000024537 0ustar00zuulzuul00000000000000././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/conf.py0000664000175000017500000002174100000000000021435 0ustar00zuulzuul00000000000000# -*- coding: utf-8 -*- # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. # Murano Release Notes documentation build configuration file, created by # sphinx-quickstart on Tue Nov 3 17:40:50 2015. # # This file is execfile()d with the current directory set to its # containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. # # All configuration values have a default; values that are commented out # serve to show the default. # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'openstackdocstheme', 'reno.sphinxext', ] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. # source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # General information about the project. project = u'Murano Agent Release Notes' copyright = u'2015, Murano Developers' # Release notes do not need a version number in the title, they # cover multiple releases. # The full version, including alpha/beta/rc tags. release = '' # The short X.Y version. version = '' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. # language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: # today = '' # Else, today_fmt is used as the format for a strftime call. # today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all # documents. # default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. # add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). # add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. # show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'native' # A list of ignored prefixes for module index sorting. # modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. # keep_warnings = False # -- Options for HTML output ---------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'openstackdocs' # openstackdocstheme options openstackdocs_repo_name = 'openstack/murano-agent' openstackdocs_auto_name = False openstackdocs_bug_project = 'murano' openstackdocs_bug_tag = '' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. # html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". # html_title = None # A shorter title for the navigation bar. Default is the same as html_title. # html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. # html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. # html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. # html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. # html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. # html_use_smartypants = True # Custom sidebar templates, maps document names to template names. # html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. # html_additional_pages = {} # If false, no module index is generated. # html_domain_indices = True # If false, no index is generated. # html_use_index = True # If true, the index is split into individual pages for each letter. # html_split_index = False # If true, links to the reST sources are added to the pages. # html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. # html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. # html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. # html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). # html_file_suffix = None # Output file base name for HTML help builder. htmlhelp_basename = 'MuranoAgentReleaseNotesdoc' # -- Options for LaTeX output --------------------------------------------- latex_elements = { # The paper size ('letterpaper' or 'a4paper'). # 'papersize': 'letterpaper', # The font size ('10pt', '11pt' or '12pt'). # 'pointsize': '10pt', # Additional stuff for the LaTeX preamble. # 'preamble': '', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ ('index', 'MuranoAgentReleaseNotes.tex', u'Murano Agent Release Notes Documentation', u'Murano Developers', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of # the title page. # latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. # latex_use_parts = False # If true, show page references after internal links. # latex_show_pagerefs = False # If true, show URL addresses after external links. # latex_show_urls = False # Documents to append as an appendix to all manuals. # latex_appendices = [] # If false, no module index is generated. # latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ('index', 'muranoagentreleasenotes', u'Murano Agent Release Notes Documentation', [u'Murano Developers'], 1) ] # If true, show URL addresses after external links. # man_show_urls = False # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ ('index', 'MuranoAgentReleaseNotes', u'Murano Agent Release Notes Documentation', u'Murano Developers', 'MuranoAgentReleaseNotes', 'One line description of project.', 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. # texinfo_appendices = [] # If false, no module index is generated. # texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. # texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. # texinfo_no_detailmenu = False # -- Options for Internationalization output ------------------------------ locale_dirs = ['locale/'] ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/index.rst0000664000175000017500000000040100000000000021765 0ustar00zuulzuul00000000000000============================ Murano Agent Release Notes ============================ .. toctree:: :maxdepth: 2 unreleased xena wallaby victoria ussuri train stein rocky queens pike ocata newton mitaka liberty ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/liberty.rst0000664000175000017500000000022200000000000022331 0ustar00zuulzuul00000000000000============================== Liberty Series Release Notes ============================== .. release-notes:: :branch: origin/stable/liberty ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/mitaka.rst0000664000175000017500000000023200000000000022126 0ustar00zuulzuul00000000000000=================================== Mitaka Series Release Notes =================================== .. release-notes:: :branch: origin/stable/mitaka ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/newton.rst0000664000175000017500000000023200000000000022172 0ustar00zuulzuul00000000000000=================================== Newton Series Release Notes =================================== .. release-notes:: :branch: origin/stable/newton ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/ocata.rst0000664000175000017500000000023000000000000021745 0ustar00zuulzuul00000000000000=================================== Ocata Series Release Notes =================================== .. release-notes:: :branch: origin/stable/ocata ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/pike.rst0000664000175000017500000000021700000000000021613 0ustar00zuulzuul00000000000000=================================== Pike Series Release Notes =================================== .. release-notes:: :branch: stable/pike ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/queens.rst0000664000175000017500000000022300000000000022160 0ustar00zuulzuul00000000000000=================================== Queens Series Release Notes =================================== .. release-notes:: :branch: stable/queens ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/rocky.rst0000664000175000017500000000022100000000000022005 0ustar00zuulzuul00000000000000=================================== Rocky Series Release Notes =================================== .. release-notes:: :branch: stable/rocky ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/stein.rst0000664000175000017500000000022100000000000022000 0ustar00zuulzuul00000000000000=================================== Stein Series Release Notes =================================== .. release-notes:: :branch: stable/stein ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/train.rst0000664000175000017500000000017600000000000022004 0ustar00zuulzuul00000000000000========================== Train Series Release Notes ========================== .. release-notes:: :branch: stable/train ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/unreleased.rst0000664000175000017500000000016000000000000023007 0ustar00zuulzuul00000000000000============================== Current Series Release Notes ============================== .. release-notes:: ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/ussuri.rst0000664000175000017500000000020200000000000022207 0ustar00zuulzuul00000000000000=========================== Ussuri Series Release Notes =========================== .. release-notes:: :branch: stable/ussuri ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/victoria.rst0000664000175000017500000000021200000000000022476 0ustar00zuulzuul00000000000000============================= Victoria Series Release Notes ============================= .. release-notes:: :branch: stable/victoria ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/wallaby.rst0000664000175000017500000000020600000000000022314 0ustar00zuulzuul00000000000000============================ Wallaby Series Release Notes ============================ .. release-notes:: :branch: stable/wallaby ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/releasenotes/source/xena.rst0000664000175000017500000000017200000000000021616 0ustar00zuulzuul00000000000000========================= Xena Series Release Notes ========================= .. release-notes:: :branch: stable/xena ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/requirements.txt0000664000175000017500000000110100000000000017415 0ustar00zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. pbr>=5.5.1 # Apache-2.0 anyjson>=0.3.3 # BSD eventlet>=0.30.1 # MIT GitPython>=3.0.5 # BSD License (3 clause) kombu>=4.6.1 # BSD oslo.config>=6.8.0 # Apache-2.0 oslo.log>=4.4.0 # Apache-2.0 oslo.service>=2.5.0 # Apache-2.0 oslo.utils>=4.8.0 # Apache-2.0 PyYAML>=5.1 # MIT semantic-version>=2.6.0 # BSD requests>=2.25.1 # Apache-2.0 cryptography>=2.7 # BSD/Apache-2.0 ././@PaxHeader0000000000000000000000000000003400000000000011452 xustar000000000000000028 mtime=1648641201.2488828 murano-agent-9.0.0/setup.cfg0000664000175000017500000000217300000000000015764 0ustar00zuulzuul00000000000000[metadata] name = murano-agent summary = Python Murano Agent description-file = README.rst license = Apache License, Version 2.0 author = OpenStack author-email = openstack-discuss@lists.openstack.org home-page = https://docs.openstack.org/murano/latest/ python-requires = >=3.6 classifier = Development Status :: 5 - Production/Stable Environment :: OpenStack Intended Audience :: Developers Intended Audience :: Information Technology License :: OSI Approved :: Apache Software License Operating System :: OS Independent Programming Language :: Python Programming Language :: Python :: Implementation :: CPython Programming Language :: Python :: 3 :: Only Programming Language :: Python :: 3 Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 [files] packages = muranoagent [entry_points] oslo.config.opts = muranoagent = muranoagent.opts:list_opts console_scripts = muranoagent = muranoagent.cmd.run:main [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 [nosetests] verbosity = 2 cover-package = muranoagent cover-html = true cover-erase = true ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/setup.py0000664000175000017500000000127100000000000015653 0ustar00zuulzuul00000000000000# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or # implied. # See the License for the specific language governing permissions and # limitations under the License. import setuptools setuptools.setup( setup_requires=['pbr>=2.0.0'], pbr=True) ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/test-requirements.txt0000664000175000017500000000057400000000000020407 0ustar00zuulzuul00000000000000# The order of packages is significant, because pip processes them in the order # of appearance. Changing the order has an impact on the overall integration # process, which may cause wedges in the gate later. hacking>=3.1.0,<3.2.0 # Apache-2.0 unittest2>=1.1.0 # BSD coverage!=4.4,>=4.0 # Apache-2.0 testtools>=2.2.0 # MIT stestr>=2.0.0 # Apache-2.0 oslotest>=3.8.0 # Apache-2.0 ././@PaxHeader0000000000000000000000000000002600000000000011453 xustar000000000000000022 mtime=1648641167.0 murano-agent-9.0.0/tox.ini0000664000175000017500000000355600000000000015464 0ustar00zuulzuul00000000000000[tox] envlist = py38,pep8 minversion = 2.0 skipsdist = True [testenv] basepython = python3 setenv = VIRTUAL_ENV={envdir} passenv = http_proxy HTTP_PROXY https_proxy HTTPS_PROXY no_proxy NO_PROXY usedevelop = True install_command = pip install {opts} {packages} deps = -r{toxinidir}/requirements.txt -r{toxinidir}/test-requirements.txt -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} commands = stestr run --slowest {posargs} whitelist_externals = bash find [testenv:pep8] commands = flake8 {posargs} [testenv:venv] commands = {posargs} [testenv:cover] commands = python setup.py test --coverage \ --coverage-package-name=muranoagent --testr-args='{posargs}' coverage report --omit '*/tests/*' [testenv:debug] commands = find . -type f -name "*.pyc" -delete oslo_debug_helper -t muranoagent/tests {posargs} [testenv:docs] deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -W -d doc/build/doctrees -b html doc/source doc/build/html [testenv:pyflakes] deps = flake8 commands = flake8 [testenv:genconfig] commands = oslo-config-generator --config-file etc/oslo-config-generator/muranoagent.conf [testenv:releasenotes] deps = -c{env:UPPER_CONSTRAINTS_FILE:https://releases.openstack.org/constraints/upper/master} -r{toxinidir}/requirements.txt -r{toxinidir}/doc/requirements.txt commands = sphinx-build -a -E -W -d releasenotes/build/doctrees -b html releasenotes/source releasenotes/build/html [flake8] ignore = F401,W503,W504 show-source = true exclude=.git,.tox,dist,doc,*lib/python*,*egg [testenv:lower-constraints] deps = -c{toxinidir}/lower-constraints.txt -r{toxinidir}/test-requirements.txt -r{toxinidir}/requirements.txt