├── .copyright.config.json ├── .copyright.templates.json ├── .functions.sh ├── .gitignore ├── CLA ├── LICENSE ├── README-libvirt.md ├── README-parallels.md ├── README-vbox.md ├── README-vmware-linux.md ├── README-vmware.md ├── README.md ├── Vagrantfile ├── bin ├── .functests ├── .probetests ├── .unittests ├── autodoc ├── cleanswift ├── kmipkey ├── memcachedstats ├── rebuildswift ├── reec ├── reinstallswift ├── remakerings ├── resetmetrics ├── resetswift ├── venv └── vtox ├── cookbooks └── swift │ ├── files │ └── default │ │ ├── etc │ │ ├── ansible │ │ │ ├── ansible.cfg │ │ │ └── hosts │ │ ├── gitconfig │ │ ├── haproxy │ │ │ └── haproxy.cfg │ │ ├── prometheus │ │ │ ├── prometheus-rules.yaml │ │ │ ├── prometheus.yaml │ │ │ └── statsd_mapping.yaml │ │ ├── swift │ │ │ ├── bench.conf │ │ │ ├── container-reconciler.conf.d │ │ │ │ └── 20_settings.conf │ │ │ ├── keymaster.conf │ │ │ └── object-expirer.conf.d │ │ │ │ └── 20_settings.conf │ │ └── systemd │ │ │ └── system │ │ │ ├── grafana.service │ │ │ ├── prometheus.service │ │ │ ├── pykmip-server.service │ │ │ └── statsd_exporter@.service │ │ └── home │ │ └── nanorc │ ├── recipes │ ├── ansible.rb │ ├── configs.rb │ ├── data.rb │ ├── default.rb │ ├── pykmip.rb │ ├── rings.rb │ ├── setup.rb │ ├── source.rb │ └── statsd_exporter.rb │ └── templates │ └── default │ ├── etc │ ├── pykmip │ │ ├── pykmip.conf.erb │ │ └── server.conf.erb │ ├── rc.local.erb │ ├── rsyncd.conf.erb │ ├── rsyncd.d │ │ └── rsync_disk.erb │ ├── ssl │ │ └── private │ │ │ └── saio.conf.erb │ └── swift │ │ ├── account-server │ │ ├── replication.conf-template.erb │ │ ├── server.conf-template.erb │ │ └── settings.conf.erb │ │ ├── base.conf-template.erb │ │ ├── container-server │ │ ├── replication.conf-template.erb │ │ ├── server.conf-template.erb │ │ └── settings.conf.erb │ │ ├── container-sync-realms.conf.erb │ │ ├── dispersion.conf.erb │ │ ├── internal-client.conf.erb │ │ ├── kmip_keymaster.conf.erb │ │ ├── node.conf-template.erb │ │ ├── object-server │ │ ├── replication.conf-template.erb │ │ ├── server.conf-template.erb │ │ └── settings.conf.erb │ │ ├── proxy-server │ │ ├── default.conf-template.erb │ │ ├── proxy-noauth.conf.d │ │ │ └── 20_settings.conf.erb │ │ └── proxy-server.conf.d │ │ │ └── 20_settings.conf.erb │ │ ├── swift.conf.erb │ │ └── test.conf.erb │ └── home │ ├── aws │ ├── config.erb │ └── credentials.erb │ ├── rclone │ └── rclone.erb │ └── s3cfg.erb ├── localrc-template └── tests ├── test-libvirt.sh ├── test-vbox.sh ├── test-vmware-linux.sh └── test-vmware.sh /.copyright.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": "NVIDIA CORPORATION", 3 | "license": "Apache-2.0", 4 | "single": false, 5 | "year": "2015-2021", 6 | "pad": 0 7 | } 8 | -------------------------------------------------------------------------------- /.copyright.templates.json: -------------------------------------------------------------------------------- 1 | { 2 | "Apache-2.0": "{short}\nCopyright (c) {year}, {author}.\nSPDX-License-Identifier: Apache-2.0" 3 | } 4 | -------------------------------------------------------------------------------- /.functions.sh: -------------------------------------------------------------------------------- 1 | # collection of shell functions to maniuplate the active bash environment 2 | clear-auth() { 3 | unset $( env | cut -d"=" -f 1 | egrep "^(OS|ST)_") 4 | } 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vagrant 2 | localrc* 3 | /*console.log 4 | /swift 5 | /python-swiftclient 6 | /swift-bench 7 | /swift-specs 8 | /liberasurecode 9 | /isa-l 10 | /pyeclib 11 | /swift-zipkin 12 | /.scratch 13 | -------------------------------------------------------------------------------- /CLA: -------------------------------------------------------------------------------- 1 | Contribution License Agreement 2 | 3 | This Contribution License Agreement (“Agreement”) is agreed to by the party 4 | signing below (“You”), and conveys certain license rights to NVIDIA Corporation 5 | and its affiliates (“NVIDIA”) for Your contributions to NVIDIA open source 6 | projects. This Agreement is effective as of the latest signature date below. 7 | 8 | 1. Definitions. 9 | 10 | “Code” means the computer software code, whether in human-readable or 11 | machine-executable form, that is delivered by You to NVIDIA under this 12 | Agreement. 13 | 14 | “Project” means any of the projects owned or managed by NVIDIA in which 15 | software is offered under a license approved by the Open Source Initiative 16 | (OSI) (www.opensource.org) and documentation offered under an OSI or a 17 | Creative Commons license (https://creativecommons.org/licenses). 18 | 19 | “Submit” is the act of uploading, submitting, transmitting, or distributing 20 | code or other content to any Project, including but not limited to 21 | communication on electronic mailing lists, source code control systems, 22 | and issue tracking systems that are managed by, or on behalf of, the 23 | Project for the purpose of discussing and improving that Project, but 24 | excluding communication that is conspicuously marked or otherwise 25 | designated in writing by You as “Not a Submission.” 26 | 27 | “Submission” means the Code and any other copyrightable material Submitted 28 | by You, including any associated comments and documentation. 29 | 30 | 2. Your Submission. You must agree to the terms of this Agreement before 31 | making a Submission to any Project. This Agreement covers any and all 32 | Submissions that You, now or in the future (except as described in Section 33 | 4 below), Submit to any Project. 34 | 35 | 3. Originality of Work. You represent that each of Your Submissions is 36 | entirely Your original work. Should You wish to Submit materials that are 37 | not Your original work, You may Submit them separately to the Project if 38 | You (a) retain all copyright and license information that was in the 39 | materials as You received them, (b) in the description accompanying Your 40 | Submission, include the phrase “Submission containing materials of a 41 | third party:” followed by the names of the third party and any licenses 42 | or other restrictions of which You are aware, and (c) follow any other 43 | instructions in the Project’s written guidelines concerning Submissions. 44 | 45 | 4. Your Employer. References to “employer” in this Agreement include Your 46 | employer or anyone else for whom You are acting in making Your Submission, 47 | e.g. as a contractor, vendor, or agent. If Your Submission is made in the 48 | course of Your work for an employer or Your employer has intellectual 49 | property rights in Your Submission by contract or applicable law, You must 50 | secure permission from Your employer to make the Submission before signing 51 | this Agreement. In that case, the term “You” in this Agreement will refer 52 | to You and the employer collectively. If You change employers in the 53 | future and desire to Submit additional Submissions for the new employer, 54 | then You agree to sign a new Agreement and secure permission from the 55 | new employer before Submitting those Submissions. 56 | 57 | 58 | 5. Licenses. 59 | 60 | a. Copyright License. You grant NVIDIA, and those who receive the Submission 61 | directly or indirectly from NVIDIA, a perpetual, worldwide, non-exclusive, 62 | royalty-free, irrevocable license in the Submission to reproduce, prepare 63 | derivative works of, publicly display, publicly perform, and distribute the 64 | Submission and such derivative works, and to sublicense any or all of the 65 | foregoing rights to third parties. 66 | 67 | b. Patent License. You grant NVIDIA, and those who receive the Submission 68 | directly or indirectly from NVIDIA, a perpetual, worldwide, non-exclusive, 69 | royalty-free, irrevocable license under Your patent claims that are 70 | necessarily infringed by the Submission or the combination of the Submission 71 | with the Project to which it was Submitted to make, have made, use, offer to 72 | sell, sell and import or otherwise dispose of the Submission alone or with 73 | the Project. 74 | 75 | c. Other Rights Reserved. Each party reserves all rights not expressly 76 | granted in this Agreement. No additional licenses or rights whatsoever 77 | (including, without limitation, any implied licenses) are granted by 78 | implication, exhaustion, estoppel or otherwise. 79 | 80 | 6. Representations and Warranties. You represent that You are legally 81 | entitled to grant the above licenses. You represent that each of Your 82 | Submissions is entirely Your original work (except as You may have 83 | disclosed under Section 3). You represent that You have secured permission 84 | from Your employer to make the Submission in cases where Your Submission 85 | is made in the course of Your work for Your employer or Your employer has 86 | intellectual property rights in Your Submission by contract or applicable 87 | law. If You are signing this Agreement on behalf of Your employer, You 88 | represent and warrant that You have the necessary authority to bind the 89 | listed employer to the obligations contained in this Agreement. You are 90 | not expected to provide support for Your Submission, unless You choose to 91 | do so. UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, AND 92 | EXCEPT FOR THE WARRANTIES EXPRESSLY STATED IN SECTIONS 3, 4, AND 6, THE 93 | SUBMISSION PROVIDED UNDER THIS AGREEMENT IS PROVIDED WITHOUT WARRANTY OF 94 | ANY KIND, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY OF NONINFRINGEMENT, 95 | MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE. 96 | 97 | 7. Notice to NVIDIA. You agree to notify NVIDIA in writing of any facts 98 | or circumstances of which You later become aware that would make Your 99 | representations in this Agreement inaccurate in any respect. 100 | 101 | 8. Information about Submissions. You agree that contributions to Projects 102 | and information about contributions may be maintained indefinitely and 103 | disclosed publicly, including Your name and other information that You 104 | submit with Your Submission. 105 | 106 | 9. Governing Law/Jurisdiction. Claims arising under this Agreement shall 107 | be governed by the laws of Delaware, excluding its principles of conflict 108 | of laws and the United Nations Convention on Contracts for the Sale of 109 | Goods. The state and/or federal courts residing in Santa Clara County, 110 | California shall have exclusive jurisdiction over any dispute or claim 111 | arising out of this Agreement. You may not export the Software in 112 | violation of applicable export laws and regulations. 113 | 114 | 10. Entire Agreement/Assignment. This Agreement is the entire agreement 115 | between the parties, and supersedes any and all prior agreements, 116 | understandings or communications, written or oral, between the parties 117 | relating to the subject matter hereof. This Agreement may be assigned by 118 | NVIDIA. 119 | 120 | 121 | 122 | 123 | Please select one of the options below and sign as indicated. By signing, 124 | You accept and agree to the terms of this Contribution License Agreement 125 | for Your present and future Submissions to NVIDIA. 126 | 127 | ___ I have sole ownership of intellectual property rights to my Submissions 128 | and I am not making Submissions in the course of work for my employer. 129 | 130 | Name (“You”): _________________________________________ 131 | Signature: _________________________________________ 132 | Date: _________________________________________ 133 | GitHub Login: _________________________________________ 134 | Email: _________________________________________ 135 | Address: _________________________________________ 136 | 137 | ___ I am making Submissions in the course of work for my employer (or my 138 | employer has intellectual property rights in my Submissions by contract or 139 | applicable law). I have permission from my employer to make Submissions and 140 | enter into this Agreement on behalf of my employer. By signing below, the 141 | defined term “You” includes me and my employer. 142 | 143 | Company Name: _________________________________________ 144 | Signature: _________________________________________ 145 | By: _________________________________________ 146 | Title: _________________________________________ 147 | Date: _________________________________________ 148 | GitHub Login: _________________________________________ 149 | Email: _________________________________________ 150 | Address: _________________________________________ 151 | 152 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /README-libvirt.md: -------------------------------------------------------------------------------- 1 | # VSAIO using libvirt 2 | 3 | VSAIO now supports running in libvirt/kvm. Be sure to pick a libvirt box in 4 | localrc and away you go. But you might need to make sure you have libvirt 5 | running for your user (unless you want to sudo everything). 6 | 7 | Install libvirtd etc. On fedora this is easy: 8 | sudo dnf install @virtualization 9 | 10 | Let's make sure its running: 11 | sudo systemctl start libvirtd 12 | sudo systemctl enable libvirtd 13 | 14 | Make sure you're user is apart of the libvirt group: 15 | sudo gpasswd -a matt libvirt 16 | 17 | We need to enable read write to domain socket for the libvirt group, uncomment 18 | and make sure these are set in /etc/libvirt/libvirtd.conf: 19 | unix_sock_group = "libvirt" 20 | auth_unix_rw = "none" 21 | auth_unix_ro = "none" 22 | 23 | Then restart libvirtd 24 | sudo systemctl restart libvirtd 25 | 26 | Add this to your localrc 27 | 28 | export LIBVIRT_DEFAULT_URI="qemu:///system" 29 | 30 | 31 | ## Supported Boxes 32 | 33 | We currently [test](tests/test-libvirt.sh) the libvirt provider with the 34 | following `VAGRANT_BOX` options: 35 | 36 | * bento/ubuntu-24.04 37 | * bento/ubuntu-22.04 38 | 39 | FWIW libvirt bringup works perfectly reliably for me, but the unittests seem to 40 | fail with hard to reproduce "timing issues" more frequently than they do for 41 | the vmware or vbox providers OMM. AFAIK no one has seen the test-libvirt.sh 42 | script complete without error. 43 | -------------------------------------------------------------------------------- /README-parallels.md: -------------------------------------------------------------------------------- 1 | vagrant-swift-all-in-one setup on Macbook M Series aarch64 processors with Parallels 2 | ======================== 3 | 4 | Host setup or installations 5 | 6 | 1. Install HomeBrew 7 | `xcode-select --install` 8 | `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` 9 | 2. Install Vagrant 10 | `brew install --cask vagrant` 11 | 3. Install Parallels 12 | Download and install from https://www.parallels.com/products/desktop/trial/ 13 | 4. Copy "localrc-template" file to your "localrc" file 14 | `cp localrc-template localrc` 15 | 5. Make changes to the below environment variables by modifying the localrc file 16 | export VAGRANT_BOX=jammy-m1 17 | export VAGRANT_DEFAULT_PROVIDER="parallels" 18 | 6. Make those environment variables to take effect 19 | `source localrc` 20 | 7. Add "192.168.8.80 saio" into /etc/hosts 21 | `sudo bash -c 'echo "192.168.8.80 saio" >> /etc/hosts'` 22 | 8. Install the vagrant plugin for parallels with `vagrant plugin install vagrant-parallels` 23 | 9.`vagrant up` 24 | 25 | The above setup was verified on macOS Sonoma on Apple M3 Pro. 26 | 27 | ## Supported Boxes 28 | 29 | We do not currently [test](tests/test-paralles.sh) the Parallels provider, it 30 | used to work with some jammy box from somewhere. 31 | -------------------------------------------------------------------------------- /README-vbox.md: -------------------------------------------------------------------------------- 1 | # VirtualBox 2 | 3 | VirtualBox is currently the default vagrant virtualization provider. But if 4 | you want to be explicit you can add the following to your `localrc` 5 | 6 | export VAGRANT_DEFAULT_PROVIDER=virtualbox 7 | 8 | ## Installation 9 | 10 | You will need to [download](https://www.virtualbox.org/wiki/Downloads) and 11 | isntall VirtualBox on your host. 12 | 13 | ## Configuration 14 | 15 | By default VirtualBox only let's you create [Host-Only Networks](https://www.virtualbox.org/manual/ch06.html#network_hostonly) 16 | in the range `192.168.56.0/21` 17 | 18 | This causes a conflict because the default `IP` assigned by the 19 | `localrc-template` is `192.168.8.80` 20 | 21 | ``` 22 | The IP address configured for the host-only network is not within the 23 | allowed ranges. Please update the address used to be within the allowed 24 | ranges and run the command again. 25 | 26 | Address: 192.168.8.80 27 | Ranges: 192.168.56.0/21 28 | 29 | Valid ranges can be modified in the /etc/vbox/networks.conf file. For 30 | more information including valid format see: 31 | 32 | https://www.virtualbox.org/manual/ch06.html#network_hostonly 33 | ``` 34 | 35 | It's recommened you configure `/etc/vbox/networks.conf` to allow your required 36 | networks, e.g. `192.168.8.0/24` 37 | 38 | ``` 39 | $ cat /etc/vbox/networks.conf 40 | * 192.168.8.0/24 41 | 42 | ``` 43 | 44 | You may need to create the file as root, 0644 permissions should be fine. 45 | 46 | Alternatively, you can change the network associated with the vagrant vm by 47 | changing the `IP` in your `localrc`. 48 | 49 | ``` 50 | $ diff localrc-template localrc.vbox-default-network 51 | 11c11 52 | < export IP=192.168.8.80 53 | --- 54 | > export IP=192.168.56.80 55 | ``` 56 | 57 | ## Supported Boxes 58 | 59 | We currently [test](tests/test-vbox.sh) the VirtualBox provider with the 60 | following `VAGRANT_BOX` options: 61 | 62 | * bento/ubuntu-24.04 63 | * bento/ubuntu-22.04 64 | * bento/ubuntu-20.04 65 | -------------------------------------------------------------------------------- /README-vmware-linux.md: -------------------------------------------------------------------------------- 1 | # VMware on Linux 2 | 3 | VMware Workstation is now available for free and supports Linux. 4 | 5 | ## Installation 6 | 7 | Registering an account with [Broadcom](https://profile.broadcom.com/web/registration) 8 | is a pre-requisite. 9 | 10 | IME, it can be challenging to find the link to 11 | [Download VMware Workstation](https://knowledge.broadcom.com/external/article/344595/downloading-and-installing-vmware-workst.html) 12 | 13 | The vagrant docs suggest the required 14 | [vagrant-vmware-utility](https://developer.hashicorp.com/vagrant/docs/providers/vmware/vagrant-vmware-utility) 15 | is available via their 16 | [official package repos](https://developer.hashicorp.com/vagrant/install/vmware#linux), 17 | but [IME](https://github.com/hashicorp/vagrant-vmware-desktop/issues/144) 18 | on Ubuntu I had to download `.deb` and install it manually: 19 | 20 | sudo dpkg -i ~/Downloads/vagrant-vmware-utility_1.0.23-1_amd64.deb 21 | 22 | You will also need to install the `vagrant-vmware-desktop` plugin for `vagrant` 23 | 24 | vagrant plugin install vagrant-vmware-desktop 25 | 26 | ## Configuration 27 | 28 | ### VMWare Kernel Module 29 | 30 | Make sure your VMware kernel modules are signed and installed: 31 | 32 | ``` 33 | $ lsmod | egrep "(vmmon|vmnet)" 34 | vmnet 73728 13 35 | vmmon 163840 1 36 | ``` 37 | 38 | Most likely if you just installed VMWare and haven't yet used it successfully 39 | those needed kernel modules will NOT be listed. Probably because they can't load: 40 | 41 | ``` 42 | $ sudo modprobe -a vmmon 43 | modprobe: ERROR: could not insert 'vmmon': Key was rejected by service 44 | ``` 45 | 46 | Hopefully you've been through the self-signed kernel module song and dance 47 | before; this script worked for me: 48 | 49 | ``` 50 | #!/bin/bash 51 | 52 | VMWARE_MOD_PREFIX=vm 53 | 54 | # create some keys for self signed modules 55 | mkdir /root/module-signing || true 56 | openssl req -new -x509 -newkey rsa:2048 \ 57 | -keyout /root/module-signing/MOK.priv -outform DER \ 58 | -out /root/module-signing/MOK.der -nodes -days 36500 \ 59 | -subj "/CN=SELFSIGNED/" 60 | # prompt to install them (with passphrase) on reboot 61 | mokutil --import /root/module-signing/MOK.der 62 | 63 | # sign the VMWare kernel modules 64 | KERNEL_VERSION=$(uname -r) 65 | for modfile in $(ls /lib/modules/${KERNEL_VERSION}/misc/${VMWARE_MOD_PREFIX}*.ko); do 66 | echo "Signing $modfile" 67 | /usr/src/linux-headers-${KERNEL_VERSION}/scripts/sign-file sha256 \ 68 | /root/module-signing/MOK.priv \ 69 | /root/module-signing/MOK.der "$modfile" 70 | done 71 | ``` 72 | 73 | ### vagrant-vmware-utility license 74 | 75 | Probably because VMware changed it's license rules in May '24 the service file 76 | provided with vagrant-vmware-utility doesn't work by default: 77 | 78 | ``` 79 | Bringing machine 'default' up with 'vmware_desktop' provider... 80 | ==> default: Cloning VMware VM: 'bento/ubuntu-24.04'. This can take some time... 81 | An error occurred while executing `vmrun`, a utility for controlling 82 | VMware machines. The command and output are below: 83 | 84 | Command: ["-T", "player", "snapshot", "/home/cgerrard/.vagrant.d/boxes/bento-VAGRANTSLASH-ubuntu-24.04/202502.21.0/amd64/vmware_desktop/ubuntu-24.04-amd64.vmx", "77a2df51-4e2f-48f2-a103-bb993b56910e", {:notify=>[:stdout, :stderr]}] 85 | 86 | Stdout: Error: The operation is not supported 87 | 88 | Stderr: Warning: program compiled against libxml 212 using older 209 89 | ``` 90 | 91 | ... what seems to be going on is the plugin is "detecting" the "wrong" license 92 | and the `-T` argument gets set to `player` instead of `ws`. 93 | 94 | The recommeneded (?) [workaround](https://github.com/hashicorp/vagrant-vmware-desktop/issues/91#issuecomment-267965302) 95 | is to change the license reported by the vmware-utility API service by adding a 96 | `-license-override professional` CLI option to the `ExecStart` line in the 97 | systemd unit file for `vagrant-vmware-utility.service` 98 | 99 | ``` 100 | $ cat /usr/lib/systemd/system/vagrant-vmware-utility.service 101 | [Unit] 102 | Description=Vagrant VMware Utility 103 | After=network.target 104 | 105 | [Service] 106 | Type=simple 107 | ExecStart=/opt/vagrant-vmware-desktop/bin/vagrant-vmware-utility api -config-file=/opt/vagrant-vmware-desktop/config/service.hcl -license-override professional 108 | Restart=on-abort 109 | 110 | [Install] 111 | WantedBy=multi-user.target 112 | ``` 113 | 114 | And then reload and restart: 115 | 116 | ``` 117 | sudo systemctl daemon-reload 118 | sudo systemctl restart vagrant-vmware-utility.service 119 | ``` 120 | 121 | ### Update localrc 122 | 123 | Tell vagrant which provider to want in your `localrc` 124 | 125 | export VAGRANT_DEFAULT_PROVIDER=vmware_desktop 126 | 127 | FWIW `export VAGRANT_DEFAULT_PROVIDER=vmware_workstation` may *seem* to work, 128 | but it won't run the custom `vmware_desktop` config in the Vagrantfile. 129 | 130 | ## Supported Boxes 131 | 132 | We currently [test](tests/test-vmware-linux.sh) the VMWare provider on Linux 133 | with the following `VAGRANT_BOX` options: 134 | 135 | * bento/ubuntu-24.04 136 | -------------------------------------------------------------------------------- /README-vmware.md: -------------------------------------------------------------------------------- 1 | vmware_desktop provider setup on Macbook M Series aarch64 processor 2 | =================================================================== 3 | 4 | 1. Install HomeBrew 5 | `xcode-select --install` 6 | `/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"` 7 | 8 | 2. Install Vagrant 9 | `brew install --cask vagrant` 10 | 11 | 3. Install Vmware Fusion 12 | 13 | Registering an account with Broadcom is a pre-requisite. 14 | 15 | Download Vmware Fusion from https://support.broadcom.com/group/ecx/productdownloads?subfamily=VMware+Fusion 16 | 17 | Note: 'Fusion' is the MAC version of Vmware Desktop. The following may 18 | also work with Vmware Desktop on Linux but has not been verified. 19 | 20 | Install vmware utility: 21 | `brew install --cask vagrant-vmware-utility` 22 | 23 | Install the vmware-desktop vagrant plugin: 24 | `sudo vagrant plugin install vagrant-vmware-desktop` 25 | 26 | 4. Create and source a localrc file, then `vagrant up`, as documented in README file. 27 | 28 | Note: useful vmware tools such as vmrun were installed at "/Applications/VMware Fusion.app/Contents/Library". 29 | Add this to your path to use: 30 | 31 | `vmrun list` 32 | 33 | to show all running vmware vm's. 34 | 35 | 36 | The above setup was verified on macOS Sequoia 15.2 on Apple M1 Pro, using: 37 | Vagrant 2.4.3 38 | Vmware Version 13.6.2 (24409261) 39 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | vagrant-swift-all-in-one 2 | ======================== 3 | 4 | A virtualization toolchain for building an [OpenStack Swift-All-In-One](https://docs.openstack.org/swift/latest/development_saio.html). 5 | 6 | This project relies on [vagrant](http://www.vagrantup.com/downloads.html), 7 | you'll need to install vagrant and setup one of the supported virtualization 8 | providers: 9 | 10 | | Provider | Host OS | Arch | 11 | | ---------------------------------- | ------------- | ----- | 12 | | [VirtualBox](README-vbox.md) | Linux | amd64 | 13 | | [libvirt](README-libvirt.md) | Linux | amd64 | 14 | | [VMware](README-vmware.md) | Mac | arm | 15 | | [VMware](README-vmware-linux.md) | Linux | amd64 | 16 | | [Parallels](README-parallels.md) | Mac | arm | 17 | 18 | localrc-template 19 | ================ 20 | 21 | Most providers will recommend you set some environ vars via your `localrc` 22 | 23 | 1. `cp localrc-template localrc` 24 | 1. `vi localrc` 25 | 26 | Additionally chef provisioning exposes some optional configuration for the vm, 27 | see `localrc-template`. 28 | 29 | 1. `source localrc` 30 | 1. `vagrant provision` 31 | 1. `vagrant ssh` 32 | 1. `rebuildswift` 33 | 34 | running-tests 35 | ============= 36 | 37 | You should be able to run most tests without too much fuss once SSH'ed into the 38 | VM. 39 | 40 | 1. `.unittests` 41 | 1. `.functests` 42 | 1. `.probetests` 43 | 1. `vtox -e pep8` 44 | 1. `vtox -e py38` 45 | 1. `vtox # run all gate checks` 46 | 47 | s3cmd 48 | ===== 49 | 50 | You know you want to play with s3api, we got you covered. 51 | 52 | ``` 53 | vagrant ssh 54 | s3cmd mb s3://s3test 55 | s3cmd ls 56 | ``` 57 | 58 | configure statsd_exporter/prometheus metrics 59 | ============================================ 60 | 61 | You should be able to optionally configure statsd_exporter/prometheus metrics for the Swift stack on the VM. 62 | 63 | ``` 64 | cp localrc-template localrc 65 | sed -i 's/^\(export STATSD_EXPORTER=\)\([^ ]*\) /\1true/g' localrc 66 | source localrc 67 | vagrant provision 68 | ``` 69 | 70 | These will expose /metrics endpoints on ports 9100-9105 which you can check directly, and configure prometheus to scrape these endpoints every 10s and retain data for up to a day; you can then create ad-hoc graphs at 71 | 72 | * http://saio:9090/graph 73 | 74 | 75 | ninja-dev-tricks 76 | ================ 77 | 78 | You should add the configured `IP` from your localrc to your `/etc/hosts` or use the default: 79 | 80 | ``` 81 | sudo bash -c 'echo "192.168.8.80 saio" >> /etc/hosts' 82 | ``` 83 | 84 | Then you can easily share snippets that talk to network services running in your Swift-All-In-One from your host! 85 | 86 | ``` 87 | curl -s http://saio:8080/info | python -m json.tool 88 | ``` 89 | 90 | A few scripts are available to make your dev life easier. 91 | 92 | 1. `vagrant up --provision` will bring up your VM in working order (useful 93 | when your VM is halted) 94 | 1. `source localrc; vagrant provision` on your host to push the new Chef bits 95 | in place (useful if you change localrc) 96 | 1. `rebuildswift` to reapply everything like it would be at the end of Chef 97 | time (useful to revert local config changes) 98 | 1. `resetswift` will wipe the drives and leave any local config changes in 99 | place (useful just to clean out Swift data) 100 | 1. `reinstallswift` will make sure all of the bin scripts are installed 101 | correctly and restart the main swift processes (useful if you change 102 | branches) 103 | 1. `autodoc [swift|swiftclient]` will build the sphinx docs and 104 | watch files for changes, and upload them to a public container on your vm 105 | so you can review them as you edit 106 | 1. `vtox` will hack the local tox.ini and setup.py so you can run tox tests 107 | successfully on the swift repo in the `/vagrant` directory 108 | 1. `reec` will rebuild/reinstall all the liberasure/pyeclib[/isa-l] bits! 109 | 1. `venv py37` will make sure your tox virtualenv is ready and let you py3 110 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | # -*- mode: ruby; -*- 2 | # vim:filetype=ruby 3 | 4 | # 5 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 6 | #SPDX-License-Identifier: Apache-2.0 7 | 8 | require 'ipaddr' 9 | 10 | DEFAULT_BOX = "bento/ubuntu-24.04" 11 | 12 | vagrant_box = (ENV['VAGRANT_BOX'] || DEFAULT_BOX) 13 | username = (ENV['VAGRANT_USERNAME'] || "vagrant") 14 | 15 | base_ip = IPAddr.new(ENV['IP'] || "192.168.8.80") 16 | hosts = { 17 | 'default' => base_ip.to_s 18 | } 19 | extra_vms = Integer(ENV['EXTRA_VMS'] || 0) 20 | (1..extra_vms).each do |i| 21 | base_ip = base_ip.succ 22 | hosts["node#{i}"] = base_ip.to_s 23 | end 24 | 25 | current_datetime = Time.now.strftime("%Y%m%d-%H%M%S") 26 | 27 | def load_key(path_or_contents) 28 | File.open(path_or_contents).read 29 | rescue Errno::ENOENT, Errno::ENAMETOOLONG 30 | path_or_contents 31 | end 32 | 33 | local_config = { 34 | "username" => username, 35 | "full_reprovision" => (ENV['FULL_REPROVISION'] || 'false').downcase == 'true', 36 | "loopback_gb" => Integer(ENV['LOOPBACK_GB'] || 4), 37 | "extra_packages" => (ENV['EXTRA_PACKAGES'] || '').split(','), 38 | "storage_policies" => (ENV['STORAGE_POLICIES'] || 'default,ec').split(','), 39 | "ec_policy" => (ENV['EC_POLICY'] || 'ec'), 40 | "servers_per_port" => Integer(ENV['SERVERS_PER_PORT'] || 0), 41 | "replication_servers" => (ENV['REPLICATION_SERVERS'] || 'false').downcase == 'true', 42 | "container_auto_shard" => (ENV['CONTAINER_AUTO_SHARD'] || 'true').downcase == 'true', 43 | "object_sync_method" => (ENV['OBJECT_SYNC_METHOD'] || 'rsync'), 44 | "encryption" => (ENV['ENCRYPTION'] || 'false').downcase == 'true', 45 | "ssl" => (ENV['SSL'] || 'false').downcase == 'true', 46 | "kmip" => (ENV['KMIP'] || 'false').downcase == 'true', 47 | "statsd_exporter" => (ENV['STATSD_EXPORTER'] || 'false').downcase == 'true', 48 | "part_power" => Integer(ENV['PART_POWER'] || 10), 49 | "replicas" => Integer(ENV['REPLICAS'] || 3), 50 | "ec_type" => (ENV['EC_TYPE'] || 'liberasurecode_rs_vand'), 51 | "ec_replicas" => Integer(ENV['EC_REPLICAS'] || 6), 52 | "ec_parity" => Integer(ENV['EC_PARITY'] || 2), 53 | "ec_duplication" => Integer(ENV['EC_DUPLICATION'] || 1), 54 | "regions" => Integer(ENV['REGIONS'] || 1), 55 | "zones" => Integer(ENV['ZONES'] || 4), 56 | "nodes" => Integer(ENV['NODES'] || 4), 57 | "disks" => Integer(ENV['DISKS'] || 4), 58 | "ec_disks" => Integer(ENV['EC_DISKS'] || 8), 59 | "swift_repo" => (ENV['SWIFT_REPO'] || 'https://github.com/openstack/swift.git'), 60 | "swift_repo_branch" => (ENV['SWIFT_REPO_BRANCH'] || 'master'), 61 | "swiftclient_repo" => (ENV['SWIFTCLIENT_REPO'] || 'https://github.com/openstack/python-swiftclient.git'), 62 | "swiftclient_repo_branch" => (ENV['SWIFTCLIENT_REPO_BRANCH'] || 'master'), 63 | "swift_bench_repo" => (ENV['SWIFTBENCH_REPO'] || 'https://github.com/openstack/swift-bench.git'), 64 | "swift_bench_repo_branch" => (ENV['SWIFTBENCH_REPO_BRANCH'] || 'master'), 65 | "liberasurecode_repo" => (ENV['LIBERASURECODE_REPO'] || 'https://github.com/openstack/liberasurecode.git'), 66 | "liberasurecode_repo_branch" => (ENV['LIBERASURECODE_REPO_BRANCH'] || 'master'), 67 | "pyeclib_repo" => (ENV['PYECLIB_REPO'] || 'https://github.com/openstack/pyeclib.git'), 68 | "pyeclib_repo_branch" => (ENV['PYECLIB_REPO_BRANCH'] || 'master'), 69 | "extra_key" => load_key(ENV['EXTRA_KEY'] || ''), 70 | "source_root" => (ENV['SOURCE_ROOT'] || '/vagrant'), 71 | "extra_source" => (ENV['EXTRA_SOURCE'] || '/vagrant/.scratch'), 72 | "nvratelimit" => (ENV['NVRATELIMIT'] || 'false').downcase == 'true', 73 | } 74 | 75 | 76 | Vagrant.configure("2") do |global_config| 77 | global_config.ssh.username = username 78 | global_config.ssh.forward_agent = true 79 | hosts.each do |vm_name, ip| 80 | global_config.vm.define vm_name do |config| 81 | hostname = vm_name 82 | if hostname == 'default' then 83 | hostname = (ENV['VAGRANT_HOSTNAME'] || 'saio') 84 | end 85 | 86 | config.vm.box = vagrant_box 87 | 88 | config.vm.provider :virtualbox do |vb, override| 89 | if Vagrant::Util::Platform.wsl? 90 | # See https://github.com/hashicorp/vagrant/issues/8604 91 | vb.customize [ "modifyvm", :id, "--uartmode1", "disconnected" ] 92 | end 93 | override.vm.hostname = hostname 94 | override.vm.network :private_network, ip: ip 95 | 96 | vb.name = "vagrant-#{hostname}-#{current_datetime}" 97 | vb.cpus = Integer(ENV['VAGRANT_CPUS'] || 1) 98 | vb.memory = Integer(ENV['VAGRANT_RAM'] || 2048) 99 | if (ENV['GUI'] || '').nil? # Why is my VM hung on boot? Find out! 100 | vb.gui = true 101 | end 102 | end 103 | 104 | config.vm.provider "libvirt" do |lv, override| 105 | override.vm.hostname = hostname 106 | override.vm.network :private_network, :ip => ip 107 | lv.cpus = Integer(ENV['VAGRANT_CPUS'] || 1) 108 | lv.memory = Integer(ENV['VAGRANT_RAM'] || 2048) 109 | lv.memorybacking :access, :mode => "shared" 110 | override.vm.synced_folder "./", "/vagrant", type: "virtiofs" 111 | end 112 | 113 | config.vm.provider "parallels" do |prl, override| 114 | override.vm.hostname = hostname 115 | prl.name = "vagrant-#{hostname}-#{current_datetime}" 116 | override.vm.network :private_network, ip: ip 117 | prl.memory = Integer(ENV['VAGRANT_RAM'] || 2048) 118 | prl.cpus = Integer(ENV['VAGRANT_CPUS'] || 1) 119 | end 120 | 121 | config.vm.provider "vmware_desktop" do |vmware, override| 122 | override.vm.hostname = hostname 123 | override.vm.network :private_network, :ip => ip 124 | vmware.vmx["displayname"] = "vagrant-#{hostname}-#{current_datetime}" 125 | unless (ENV['GUI'] || '').empty? 126 | # use a gui to get the vm to show up in the vmware management app, 127 | # but they seem to stick around in the app after vagrant destroy 128 | vmware.gui = true 129 | end 130 | vmware.vmx["memsize"] = Integer(ENV['VAGRANT_RAM'] || 2048) 131 | vmware.vmx["numvcpus"] = Integer(ENV['VAGRANT_CPUS'] || 1) 132 | end 133 | 134 | if Vagrant::Util::Platform.wsl? 135 | hostpath = File.dirname(__FILE__) 136 | if !Vagrant::Util::Platform.wsl_drvfs_path? hostpath 137 | puts "/vagrant will be one-way-synced! Consider using a "\ 138 | "Windows checkout, rather than keeping it under WSL." 139 | # DO NOT include --delete; with that, we blow away our git repos on reload 140 | override.vm.synced_folder hostpath, "/vagrant", type: "rsync", 141 | rsync__args: ["--verbose", "--archive", "-z"] 142 | end 143 | end 144 | 145 | config.vm.provider :aws do |v, override| 146 | override.vm.synced_folder ".", "/vagrant", type: "rsync", 147 | rsync__args: ["--verbose", "--archive", "--delete", "-z"] 148 | override.ssh.private_key_path = ENV['SSH_PRIVATE_KEY_PATH'] 149 | 150 | v.access_key_id = ENV['AWS_ACCESS_KEY_ID'] 151 | v.secret_access_key = ENV['AWS_SECRET_ACCESS_KEY'] 152 | v.region = ENV['AWS_REGION'] 153 | v.ami = ENV['AWS_AMI'] 154 | v.instance_type = ENV['AWS_INSTANCE_TYPE'] 155 | v.elastic_ip = ENV['AWS_ELASTIC_IP'] 156 | v.keypair_name = ENV['AWS_KEYPAIR_NAME'] 157 | security_groups = ENV['AWS_SECURITY_GROUPS'] 158 | v.security_groups = security_groups.split(',') unless security_groups.nil? 159 | v.tags = {'Name' => 'swift'} 160 | end 161 | 162 | config.vm.provision :chef_solo do |chef| 163 | chef.arguments = "--chef-license accept" 164 | chef.provisioning_path = "/etc/chef" 165 | chef.add_recipe "swift" 166 | chef.json = { 167 | "ip" => ip, 168 | "hostname" => hostname, 169 | "saio_crt_path" => "/etc/ssl/private/saio.crt", 170 | } 171 | chef.json.merge! local_config 172 | if chef.json['ssl'] then 173 | chef.json['base_uri'] = "https://#{hostname}" 174 | else 175 | chef.json['base_uri'] = "http://#{hostname}:8080" 176 | end 177 | chef.json['auth_uri'] = "#{chef.json['base_uri']}/auth/v1.0" 178 | end 179 | end 180 | end 181 | end 182 | -------------------------------------------------------------------------------- /bin/.functests: -------------------------------------------------------------------------------- 1 | ../swift/.functests -------------------------------------------------------------------------------- /bin/.probetests: -------------------------------------------------------------------------------- 1 | ../swift/.probetests -------------------------------------------------------------------------------- /bin/.unittests: -------------------------------------------------------------------------------- 1 | ../swift/.unittests -------------------------------------------------------------------------------- /bin/autodoc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | from __future__ import print_function 8 | import argparse 9 | import os 10 | try: 11 | import queue 12 | except ImportError: 13 | # py2 14 | import Queue as queue 15 | import sys 16 | import threading 17 | 18 | PROJECTS = { 19 | 'swift': { 20 | 'root': '/vagrant/swift/doc/', 21 | 'dir': ['../swift', 'saio'], 22 | 'container': 'doc', 23 | }, 24 | 'swift-api-ref': { 25 | 'root': '/vagrant/swift/api-ref/', 26 | 'dir': [], 27 | 'container': 'api-ref', 28 | }, 29 | 'swiftclient': { 30 | 'root': '/vagrant/python-swiftclient/doc/', 31 | 'dir': [], 32 | 'container': 'swiftclient', 33 | } 34 | } 35 | 36 | parser = argparse.ArgumentParser() 37 | parser.add_argument('-r', '--root', default=None, 38 | help="the root of the doc tree") 39 | parser.add_argument('--dir', action='append', default=[], 40 | help="extra dirs to append, if relative path, " 41 | "it's relative to the root") 42 | parser.add_argument('--container', default=None, 43 | help="the swift container into which the " 44 | "compiled html will be uploaded") 45 | parser.add_argument('project', nargs='?', default='swift', 46 | choices=PROJECTS.keys(), 47 | help="use defaults for pre-configured projects") 48 | 49 | 50 | def iter_path_mtime(source_dir): 51 | for root, dirs, files in os.walk(source_dir): 52 | for filename in files: 53 | if filename.rsplit('.', 1)[-1] not in ('rst', 'py', 'inc', 'yaml'): 54 | continue 55 | full_path = os.path.join(root, filename) 56 | current_mtime = os.path.getmtime(full_path) 57 | yield full_path, current_mtime 58 | 59 | 60 | def watch_changed_files(q, *source_dirs): 61 | last_changed_time = {} 62 | while True: 63 | full_pass_has_changes = False 64 | for source_dir in source_dirs: 65 | for path, mtime in iter_path_mtime(source_dir): 66 | if (path in last_changed_time and 67 | last_changed_time[path] < mtime): 68 | yield path 69 | full_pass_has_changes = True 70 | last_changed_time = {} 71 | last_changed_time[path] = mtime 72 | if not full_pass_has_changes: 73 | # sleep for one second (or till user hits enter...) 74 | try: 75 | q.get(timeout=1.0) 76 | except queue.Empty: 77 | pass 78 | else: 79 | yield 'User says path...' 80 | 81 | 82 | def main(): 83 | options = parser.parse_args() 84 | if options.root: 85 | root = options.root 86 | montior_paths = options.dir 87 | default_container = 'doc' 88 | else: 89 | root = PROJECTS[options.project]['root'] 90 | montior_paths = PROJECTS[options.project]['dir'] + options.dir 91 | default_container = PROJECTS[options.project]['container'] 92 | 93 | container = options.container or default_container 94 | source_dir = os.path.join(root, 'source') 95 | build_dir = os.path.join(root, 'build/html') 96 | extra_dirs = [os.path.join(root, path) for path in montior_paths] 97 | 98 | # intial build 99 | rv = os.system('vtox -e docs') 100 | if rv != 0: 101 | # bail on build fail 102 | return rv 103 | os.chdir(build_dir) 104 | os.system('swift post %s -r .r:*,.rlistings -m web-index:index.html' % 105 | container) 106 | print('uploading...') 107 | os.system('swift upload --changed %s . > /dev/null' % container) 108 | print('done...') 109 | os.system('swift stat -v %s index.html | grep URL' % container) 110 | # we're gunna let the user hit enter to rebuild immediately 111 | q = queue.Queue() 112 | 113 | def get_input(): 114 | while True: 115 | if sys.version_info < (3,): 116 | q.put(raw_input()) 117 | else: 118 | q.put(input()) 119 | continue_thread = threading.Thread(target=get_input) 120 | continue_thread.daemon = True 121 | continue_thread.start() 122 | for filename in watch_changed_files(q, source_dir, *extra_dirs): 123 | print('%s has CHANGED!' % filename) 124 | print('rebuilding...') 125 | os.system('tox -e docs') 126 | print('uploading...') 127 | os.system('swift upload --changed %s . > /dev/null' % container) 128 | print('done...') 129 | os.system('swift stat -v %s index.html | grep URL' % container) 130 | 131 | 132 | if __name__ == "__main__": 133 | try: 134 | sys.exit(main()) 135 | except KeyboardInterrupt: 136 | print('quit.') 137 | -------------------------------------------------------------------------------- /bin/cleanswift: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | 9 | swift-init all stop || : 10 | swift-orphans -a 0 -k KILL || : 11 | find /var/log/swift -type f -delete || : 12 | find /var/cache/swift* -type f -name *.recon -delete 13 | 14 | for d in $(ls -d /srv/node*/*); do 15 | mount | grep -q $d && sudo umount $d 16 | done 17 | sudo rm -rf /srv/node* 18 | sudo rm -f /var/lib/swift/disk* 19 | 20 | for fname in /var/log/debug /var/log/messages /var/log/rsyncd.log /var/log/syslog; do 21 | sudo truncate --size 0 $fname 22 | done 23 | sudo service rsyslog restart 24 | -------------------------------------------------------------------------------- /bin/kmipkey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | import errno 8 | import kmip.core.enums 9 | import kmip.pie.client 10 | import kmip.pie.exceptions 11 | import logging 12 | import socket 13 | import sys 14 | import time 15 | 16 | logging.basicConfig(level=logging.INFO) 17 | 18 | 19 | def main(): 20 | with kmip.pie.client.ProxyKmipClient() as client: 21 | for i in range(3): 22 | secret_id = str(i + 1) 23 | try: 24 | client.get(secret_id) 25 | except kmip.pie.exceptions.KmipOperationFailure as e: 26 | if e.reason != kmip.core.enums.ResultReason.ITEM_NOT_FOUND: 27 | raise 28 | client.create(kmip.core.enums.CryptographicAlgorithm.AES, 256) 29 | logging.info('KEY %s CREATED', secret_id) 30 | else: 31 | logging.info('KEY %s FOUND', secret_id) 32 | 33 | 34 | if __name__ == "__main__": 35 | try: 36 | sys.exit(main()) 37 | except socket.error as e: 38 | if e.errno != errno.ECONNREFUSED: 39 | raise 40 | # Give the kmip server more of a chance to start up 41 | time.sleep(3) 42 | sys.exit(main()) 43 | -------------------------------------------------------------------------------- /bin/memcachedstats: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | echo stats | nc -N localhost 11211 8 | -------------------------------------------------------------------------------- /bin/rebuildswift: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | /vagrant/bin/cleanswift 8 | sudo rm -fr /etc/swift/* /var/run/swift/* /var/cache/swift/* /etc/pykmip/* \ 9 | /etc/rsyncd.* /etc/ssl/private/saio.* /etc/haproxy/haproxy.cfg 10 | sed 's/"full_reprovision": false/"full_reprovision": true/g' /etc/chef/dna.json > /tmp/reload.json 11 | sudo chef-solo -c /etc/chef/solo.rb -j /tmp/reload.json 12 | -------------------------------------------------------------------------------- /bin/reec: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | set -ex 8 | if [ -d $SOURCE_ROOT/isa-l ]; then 9 | sudo apt install nasm 10 | cd $SOURCE_ROOT/isa-l 11 | ./autogen.sh 12 | ./configure 13 | make 14 | cd /usr/lib 15 | sudo rm libisal.* || true 16 | cd - 17 | sudo make install 18 | fi 19 | cd $SOURCE_ROOT/liberasurecode 20 | ./autogen.sh 21 | ./configure 22 | make 23 | cd /usr/local/lib 24 | sudo rm liberasurecode.* libnullcode.* libXorcode.* || true 25 | cd - 26 | sudo make install 27 | sudo ldconfig 28 | cd $SOURCE_ROOT/pyeclib 29 | rm -fr *.so build/ 30 | sudo pip install -e . 31 | -------------------------------------------------------------------------------- /bin/reinstallswift: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | sed 's/"full_reprovision": false/"full_reprovision": true/g' /etc/chef/dna.json > /tmp/reload.json 9 | sudo chef-solo -c /etc/chef/solo.rb -j /tmp/reload.json -o swift::source 10 | swift-init restart main 11 | echo "READY!" 12 | -------------------------------------------------------------------------------- /bin/remakerings: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | rm -f /etc/swift/*.builder /etc/swift/*.ring.gz \ 8 | /etc/swift/backups/*.builder /etc/swift/backups/*.ring.gz 9 | 10 | sudo chef-solo -c /etc/chef/solo.rb -j /etc/chef/dna.json -o swift::rings 11 | -------------------------------------------------------------------------------- /bin/resetmetrics: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | sudo systemctl stop prometheus.service 3 | sudo rm -rf /tmp/prom/data/* 4 | sudo systemctl restart 'statsd_exporter@*' 5 | sudo systemctl start prometheus.service 6 | -------------------------------------------------------------------------------- /bin/resetswift: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | /vagrant/bin/cleanswift 9 | sudo chef-solo -c /etc/chef/solo.rb -j /etc/chef/dna.json -o swift::data 10 | sudo service rsyslog restart 11 | sudo service memcached restart 12 | -------------------------------------------------------------------------------- /bin/venv: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | set -e 8 | TOXENV=$1 9 | if [ ! -d ~/.tox-swift/${TOXENV}/ ]; then 10 | cd /vagrant/swift 11 | unset TMPDIR 12 | vtox -e ${TOXENV} --notest 13 | cd - 14 | fi 15 | RCFILE=~/.venv.${TOXENV} 16 | cat < $RCFILE 17 | . ~/.profile 18 | . ~/.bashrc 19 | . ~/.tox-swift/${TOXENV}/bin/activate 20 | EOF 21 | trap "rm $RCFILE" EXIT 22 | $SHELL --rcfile $RCFILE 23 | -------------------------------------------------------------------------------- /bin/vtox: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | # tox wrapper for vagrant 8 | set -e 9 | cd /vagrant/swift 10 | sed -i "/envlist/ a\ 11 | toxworkdir = $HOME/.tox-swift 12 | " tox.ini 13 | set +e 14 | tox $@ 15 | error=$? 16 | sed -i '/toxworkdir/d' tox.ini 17 | cd - 18 | 19 | # If setup.py or setup.cfg are newer than swift.egg-info, then tox 20 | # will always reinstall Swift in the test virtualenv, which is really 21 | # slow. It wouldn't be so bad if that reinstallation would update the 22 | # timestamp on swift.egg-info, but it doesn't, so once you get an 23 | # update to setup.py or setup.cfg, your test runs are slow forever 24 | # after. 25 | # 26 | # To work around this, after a successful test run, touch 27 | # swift.egg-info to update its mtime. This way, if there really is a 28 | # change to setup.py/setup.cfg, then one (slow) reinstall will occur, 29 | # and then subsequent test runs will use the existing one. 30 | if [ $error -eq 0 -a -d swift.egg-info ]; then 31 | touch swift.egg-info 32 | fi 33 | 34 | exit $error 35 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [defaults] 2 | host_key_checking = False 3 | executable = /bin/bash 4 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/ansible/hosts: -------------------------------------------------------------------------------- 1 | all: 2 | hosts: 3 | saio: 4 | vars: 5 | ansible_user: vagrant 6 | ansible_private_key_file: /vagrant/.vagrant/machines/default/virtualbox/private_key 7 | ansible_shell_type: sh 8 | zuul: 9 | project: 10 | src_dir: swift 11 | executor: 12 | log_root: /var/log/ansible 13 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/gitconfig: -------------------------------------------------------------------------------- 1 | [safe] 2 | directory = * 3 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/haproxy/haproxy.cfg: -------------------------------------------------------------------------------- 1 | global 2 | log /dev/log local0 3 | log /dev/log local1 notice 4 | chroot /var/lib/haproxy 5 | stats socket /run/haproxy/admin.sock mode 660 level admin 6 | stats timeout 30s 7 | user haproxy 8 | group haproxy 9 | daemon 10 | 11 | # Default SSL material locations 12 | ca-base /etc/ssl/certs 13 | crt-base /etc/ssl/private 14 | 15 | # Default ciphers to use on SSL-enabled listening sockets. 16 | # For more information, see ciphers(1SSL). This list is from: 17 | # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ 18 | # (as retrieved on 2020-01-04) 19 | ssl-default-bind-options no-sslv3 20 | ssl-default-bind-ciphers ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS:!AESCCM 21 | 22 | ssl-default-server-options no-sslv3 23 | ssl-default-server-ciphers ECDH+AESGCM:ECDH+CHACHA20:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:RSA+AESGCM:RSA+AES:!aNULL:!MD5:!DSS:!AESCCM 24 | 25 | tune.ssl.default-dh-param 2048 26 | 27 | defaults 28 | log global 29 | option dontlognull 30 | timeout connect 5000 31 | timeout client 50000 32 | timeout server 50000 33 | 34 | frontend www-http 35 | bind *:80 36 | default_backend www-backend 37 | 38 | frontend www-https 39 | bind *:443 ssl crt /etc/ssl/private/saio.pem 40 | default_backend www-backend 41 | 42 | backend www-backend 43 | server www-1 127.0.0.1:8080 send-proxy 44 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/prometheus/prometheus-rules.yaml: -------------------------------------------------------------------------------- 1 | groups: 2 | - name: Cluster aggregates 3 | interval: 10s 4 | rules: 5 | - record: cluster:object_server_requests_per_second 6 | expr: sum (rate(object_server_timing_count[30s])) by (method) 7 | - record: cluster:container_server_requests_per_second 8 | expr: sum (rate(container_server_timing_count[30s])) by (method) 9 | - record: cluster:account_server_requests_per_second 10 | expr: sum (rate(account_server_timing_count[30s])) by (method) 11 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/prometheus/prometheus.yaml: -------------------------------------------------------------------------------- 1 | scrape_configs: 2 | - job_name: 'saio' 3 | scrape_interval: 10s 4 | static_configs: 5 | - targets: 6 | - 'localhost:9100' 7 | labels: 8 | host: 'proxy' 9 | 10 | # backend servers 11 | - targets: 12 | - 'localhost:9101' 13 | labels: 14 | host: 'node1' 15 | - targets: 16 | - 'localhost:9102' 17 | labels: 18 | host: 'node2' 19 | - targets: 20 | - 'localhost:9103' 21 | labels: 22 | host: 'node3' 23 | - targets: 24 | - 'localhost:9104' 25 | labels: 26 | host: 'node4' 27 | 28 | # noauth proxy server 29 | - targets: 30 | - 'localhost:9105' 31 | labels: 32 | host: 'noauth' 33 | 34 | rule_files: 35 | - /etc/prometheus/prometheus-rules.yaml 36 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/prometheus/statsd_mapping.yaml: -------------------------------------------------------------------------------- 1 | mappings: 2 | ## Swift statsd -> statsd exporter 3 | ### account/container/container auditor 4 | - match: ^(internal|subrequest)*(\.)*(account|container|object)-auditor(-[0-9]*)?\.timing$ 5 | match_type: regex 6 | name: "${3}_auditor_timing" 7 | labels: 8 | hostname: "$2$1" 9 | 10 | - match: ^(internal|subrequest)*(\.)*(account|container|object)-auditor(-[0-9]*)?\.(\w+)$ 11 | match_type: regex 12 | name: "${3}_auditor" 13 | labels: 14 | hostname: "$2$1" 15 | metric: "$4" 16 | 17 | ### Account-reaper 18 | - match: ^(internal|subrequest)*(\.)*account-reaper(-[0-9]*)?\.timing$ 19 | match_type: regex 20 | name: "account_reaper_timing" 21 | labels: 22 | hostname: "$2$1" 23 | 24 | - match: ^(internal|subrequest)*(\.)*account-reaper(-[0-9]*)?\.return_codes.(\w+)$ 25 | match_type: regex 26 | name: "account_reaper" 27 | labels: 28 | hostname: "$2$1" 29 | metric: "return_codes" 30 | code: "$4" 31 | 32 | - match: ^(internal|subrequest)*(\.)*account-reaper(-[0-9]*)?\.([a-zA-Z]*)_([a-zA-Z_]*)$ 33 | match_type: regex 34 | name: "account_reaper" 35 | labels: 36 | hostname: "$2$1" 37 | metric: "$4" 38 | 39 | - match: ^(internal|subrequest)*(\.)*account-reaper(-[0-9]*)?\.(\w+)$ 40 | match_type: regex 41 | name: "account_reaper" 42 | labels: 43 | hostname: "$2$1" 44 | metric: "$4" 45 | 46 | 47 | ### account/container/object server 48 | 49 | - match: ^(internal|subrequest)*(\.)*(account|container|object)-server(-[0-9]*)?([-r]*)\.([A-Z]*)\.errors.timing$ 50 | match_type: regex 51 | name: "${3}_server_errors_timing" 52 | labels: 53 | hostname: "$2$1" 54 | server: "$5" 55 | method: "$6" 56 | 57 | - match: ^(internal|subrequest)*(\.)*(account|container|object)-server(-[0-9]*)?([-r]*)\.([A-Z]*)\.timing$ 58 | match_type: regex 59 | name: "${3}_server_timing" 60 | labels: 61 | hostname: "$2$1" 62 | server: "$5" 63 | method: "$6" 64 | 65 | - match: ^(internal|subrequest)*(\.)*(account|container|object)-server(-[0-9]*)?([-r]*)\.([A-Z]*)\.([a-z0-9]*)\.timing$ 66 | match_type: regex 67 | name: "${3}_server_device_timing" 68 | labels: 69 | hostname: "$2$1" 70 | server: "$5" 71 | method: "$6" 72 | device: "$7" 73 | 74 | ### object server 75 | 76 | - match: ^(internal|subrequest)*(\.)*object-server(-[0-9]*)?([-r]*)\.(\w+)$ 77 | match_type: regex 78 | name: "object_server" 79 | labels: 80 | hostname: "$2$1" 81 | server: "$4" 82 | method: "$5" 83 | 84 | 85 | ### account/container replicator 86 | 87 | - match: ^(internal|subrequest)*(\.)*(account|container)-replicator(-[0-9]*)?\.timing$ 88 | match_type: regex 89 | name: "${3}_replicator_timing" 90 | labels: 91 | hostname: "$2$1" 92 | 93 | - match: ^(internal|subrequest)*(\.)*(account|container)-(replicator|sharder)(-[0-9]*)?\.removes\.([a-z0-9]*)$ 94 | match_type: regex 95 | name: "${3}_${4}_removes" 96 | labels: 97 | hostname: "$2$1" 98 | device: "$6" 99 | 100 | - match: ^(internal|subrequest)*(\.)*(account|container)-replicator(-[0-9]*)?\.(\w+)$ 101 | match_type: regex 102 | name: "${3}_replicator" 103 | labels: 104 | hostname: "$2$1" 105 | metric: "$5" 106 | 107 | ### object replicator/reconstructor 108 | 109 | - match: ^(internal|subrequest)*(\.)*object-(replicator|reconstructor)(-[0-9]*)?\.partition\.(\w+)\.timing$ 110 | match_type: regex 111 | name: "object_${3}_partition_timing" 112 | labels: 113 | hostname: "$2$1" 114 | metric: "$5" 115 | 116 | - match: ^(internal|subrequest)*(\.)*object-(replicator|reconstructor)(-[0-9]*)?\.partition\.(.[a-zA-Z0-9-_]*)\.count(\.)*([a-z0-9]*)*$ 117 | match_type: regex 118 | name: "object_${3}_partition_count" 119 | labels: 120 | hostname: "$2$1" 121 | metric: "$5" 122 | device: "$7" 123 | 124 | - match: ^(internal|subrequest)*(\.)*object-(replicator|reconstructor)(-[0-9]*)?\.suffix\.(\w+)$ 125 | match_type: regex 126 | name: "object_${3}_suffix" 127 | labels: 128 | hostname: "$2$1" 129 | metric: "$5" 130 | 131 | 132 | ### container sync 133 | 134 | - match: ^(internal|subrequest)*(\.)*container-sync(-[0-9]*)?\.(\w+)\.timing$ 135 | match_type: regex 136 | name: "container_sync_timing" 137 | labels: 138 | hostname: "$2$1" 139 | metric: "$4" 140 | 141 | 142 | - match: ^(internal|subrequest)*(\.)*container-sync(-[0-9]*)?\.(\w+)$ 143 | match_type: regex 144 | name: "container_sync" 145 | labels: 146 | hostname: "$2$1" 147 | metric: "$4" 148 | 149 | 150 | ### container/object updater timing 151 | 152 | - match: ^(internal|subrequest)*(\.)*(container|object)-updater(-[0-9]*)?\.timing$ 153 | match_type: regex 154 | name: "${3}_updater_timing" 155 | labels: 156 | hostname: "$2$1" 157 | 158 | ### object updater status timing 159 | - match: ^(internal|subrequest)*(\.)*object-updater(-[0-9]*)?\.updater\.timing\.status\.([0-9]{3})$ 160 | match_type: regex 161 | name: "object_updater_status_timing" 162 | labels: 163 | hostname: "$2$1" 164 | status: "$4" 165 | 166 | ### container/object updater metrics 167 | - match: ^(internal|subrequest)*(\.)*(container|object)-updater(-[0-9]*)?\.(\w+)$ 168 | match_type: regex 169 | name: "${3}_updater" 170 | labels: 171 | hostname: "$2$1" 172 | metric: "$5" 173 | 174 | ### object expirer 175 | 176 | - match: ^(internal|subrequest)*(\.)*object-expirer(-[0-9]*)?\.timing$ 177 | match_type: regex 178 | name: "object_expirer_timing" 179 | labels: 180 | hostname: "$2$1" 181 | 182 | - match: ^(internal|subrequest)*(\.)*object-expirer(-[0-9]*)?\.(\w+)$ 183 | match_type: regex 184 | name: "object_expirer" 185 | labels: 186 | hostname: "$2$1" 187 | metric: "$4" 188 | 189 | ### proxy server 190 | 191 | - match: ^(internal|subrequest)*(\.)*proxy-server\.errors$ 192 | match_type: regex 193 | name: "proxy_server_errors" 194 | labels: 195 | hostname: "$2$1" 196 | 197 | - match: ^(internal|subrequest)*(\.)*proxy-server\.(account|container|object)\.([hc]{1}[a-z_]*)$ 198 | match_type: regex 199 | name: "proxy_server" 200 | labels: 201 | hostname: "$2$1" 202 | type: "$3" 203 | metric: "$4" 204 | 205 | - match: ^(internal|subrequest)*(\.)*proxy-server\.(account|container|object)\.GET\.([0-9]{3})\.first-byte\.timing$ 206 | match_type: regex 207 | name: "proxy_server_get_first_byte_timing" 208 | labels: 209 | hostname: "$2$1" 210 | type: "$3" 211 | status: "$4" 212 | 213 | - match: ^(internal|subrequest)*(\.)*proxy-server\.(account|container|object)\.([A-Z_]*)\.([0-9]{3})\.timing$ 214 | match_type: regex 215 | name: "proxy_server_timing" 216 | labels: 217 | hostname: "$2$1" 218 | type: "$3" 219 | method: "$4" 220 | status: "$5" 221 | 222 | - match: ^(internal|subrequest)*(\.)*proxy-server\.(account|container|object)\.([A-Z_]*)\.([0-9]{3})\.xfer$ 223 | match_type: regex 224 | name: "proxy_server_xfer" 225 | labels: 226 | hostname: "$2$1" 227 | type: "$3" 228 | method: "$4" 229 | status: "$5" 230 | 231 | - match: ^(internal|subrequest)*(\.)*proxy-server\.object\.policy\.([0-9]*)\.([A-Z_]*)\.([0-9]{3})\.timing$ 232 | match_type: regex 233 | name: "proxy_server_policy_timing" 234 | labels: 235 | hostname: "$2$1" 236 | policy: "$3" 237 | method: "$4" 238 | status: "$5" 239 | 240 | - match: ^(internal|subrequest)*(\.)*proxy-server\.object\.policy\.([0-9]*)\.GET\.([0-9]{3})\.first-byte\.timing$ 241 | match_type: regex 242 | name: "proxy_server_policy_get_first_byte_timing" 243 | labels: 244 | hostname: "$2$1" 245 | policy: "$3" 246 | status: "$4" 247 | 248 | - match: ^(internal|subrequest)*(\.)*proxy-server\.object\.policy\.([0-9]*)\.([A-Z_]*)\.([0-9]{3})\.xfer$ 249 | match_type: regex 250 | name: "proxy_server_policy_xfer" 251 | labels: 252 | hostname: "$2$1" 253 | policy: "$3" 254 | method: "$4" 255 | status: "$5" 256 | 257 | ### Memcached access timing: .memcached.[.].timing 258 | - match: ^(internal|subrequest)*(\.)*(swift|proxy-server|container[a-zA-Z0-9-]*|object[a-zA-Z0-9-]*)\.memcached\.(\w+)\.([a-z_]*)\.*timing$ 259 | match_type: regex 260 | name: "memcached_timing" 261 | labels: 262 | hostname: "$2$1" 263 | service: "$3" 264 | command: "$4" 265 | error: "$5" 266 | 267 | ### Proxy-server error_limiter 268 | - match: ^(internal|subrequest)*(\.)*proxy-server\.error_limiter\.(\w+)$ 269 | match_type: regex 270 | name: "proxy_server_error_limiter" 271 | labels: 272 | hostname: "$2$1" 273 | metric: "$3" 274 | 275 | ### container sharder 276 | 277 | - match: ^(internal|subrequest)*(\.)*container-sharder(-[0-9]*)?\.timing$ 278 | match_type: regex 279 | name: "container_sharder_timing" 280 | labels: 281 | hostname: "$2$1" 282 | 283 | - match: ^(internal|subrequest)*(\.)*container-sharder(-[0-9]*)?\.removes\.([a-z0-9]*)$ 284 | match_type: regex 285 | name: "container_sharder_removes" 286 | labels: 287 | hostname: "$2$1" 288 | device: "$4" 289 | 290 | - match: ^(internal|subrequest)*(\.)*container-sharder(-[0-9]*)?\.(\w+)$ 291 | match_type: regex 292 | name: "container_sharder" 293 | labels: 294 | hostname: "$2$1" 295 | metric: "$4" 296 | 297 | - match: ^(internal|subrequest)*(\.)*container-sharder(-[0-9]*)?\.sharder\.sharding\.(.*)$ 298 | match_type: regex 299 | name: "container_sharder_sharding" 300 | labels: 301 | hostname: "$2$1" 302 | metric: "$4" 303 | 304 | ### container shard range: (proxy-server.[container|object].shard_[updating|listing].cache.[miss|skip|force_skip|disabled|error|bypass].{CODE}) 305 | ### container shard range: (proxy-server.[container|object].shard_[updating|listing].cache.hit) 306 | - match: ^(internal|subrequest)*(\.)*(proxy-server)\.([\w+]*)\.*(shard_\w+)\.cache\.(miss|skip|force_skip|disabled|error|hit|bypass)\.*([0-9]{3})*$ 307 | match_type: regex 308 | name: "container_shard_ranges_cache" 309 | labels: 310 | hostname: "$2$1" 311 | service: "$3" 312 | target: "$4" 313 | method: "$5" 314 | metric: "$6" 315 | status: "$7" 316 | 317 | ### container shard range: (proxy-server.[container|object].shard_[updating|listing].infocache.hit) 318 | - match: ^(internal|subrequest)*(\.)*(proxy-server)\.([\w+]*)\.*(shard_\w+)\.infocache\.(\w+)$ 319 | match_type: regex 320 | name: "container_shard_ranges_infocache" 321 | labels: 322 | hostname: "$2$1" 323 | service: "$3" 324 | target: "$4" 325 | method: "$5" 326 | metric: "$6" 327 | 328 | ### account/container info cache (memcache) and infocache (infocache) 329 | ### (proxy-server).[account|container].info.cache.hit) 330 | ### (proxy-server).[account|container].info.cache.[miss|skip|disabled].status_int 331 | - match: ^(internal|subrequest)*(\.)*(proxy-server)\.(account|container)\.info\.cache\.([a-zA-Z_]+)(\.)*([0-9]{3})*$ 332 | match_type: regex 333 | name: "${4}_info_cache" 334 | labels: 335 | hostname: "$2$1" 336 | service: "$3" 337 | metric: "$5" 338 | status: "$7" 339 | 340 | ### (proxy-server).[account|container].info.infocache.hit) 341 | - match: ^(internal|subrequest)*(\.)*(proxy-server)\.(account|container)\.info\.infocache\.([a-zA-Z_]+)$ 342 | match_type: regex 343 | name: "${4}_info_infocache" 344 | labels: 345 | hostname: "$2$1" 346 | service: "$3" 347 | metric: "$5" 348 | 349 | ### tempauth 350 | 351 | - match: ^(internal|subrequest)*(\.)*tempauth\.(\w+)\.(\w+)$ 352 | match_type: regex 353 | name: "middleware_tempauth" 354 | labels: 355 | hostname: "$2$1" 356 | reseller_prefix: "$3" 357 | metric: "$4" 358 | 359 | ### tempurl/formpost digests 360 | - match: ^(internal|subrequest)*(\.)*proxy-server\.(tempurl|formpost)\.digests\.(\w+)$ 361 | match_type: regex 362 | name: "middleware_${3}_digests" 363 | labels: 364 | hostname: "$2$1" 365 | digest: "$4" 366 | 367 | ### s3api 368 | 369 | - match: ^(internal|subrequest)*(\.)*s3api\.([0-9]{3})\.([a-zA-Z_]+)\.*([a-zA-Z_-]*)$ 370 | match_type: regex 371 | name: "middleware_s3api" 372 | labels: 373 | hostname: "$2$1" 374 | status: "$3" 375 | error: "$4" 376 | reason: "$5" 377 | 378 | - match: ^(internal|subrequest)*(\.)*proxy-server\.info\.(\w+)$ 379 | match_type: regex 380 | name: "proxy_server_info" 381 | labels: 382 | hostname: "$2$1" 383 | metric: "$3" 384 | 385 | ### in a labeled-metrics world, everything should have a "swift_" prefix 386 | ### (hopefully?) 387 | - match: ^swift_.* 388 | match_type: regex 389 | name: "$0" 390 | 391 | ### new metrics we're missing with hostname 392 | ### Note: when the metric name is unknown and may contain '.' we cannot 393 | ### distinguish arbitrary hostnames, so we make a best effort to match 394 | ### hostnames ending '.net'. This is unfortunately brittle. 395 | - match: ([a-zA-Z0-9-]*[a-zA-Z0-9.]*\.net)\.(.*)$ 396 | match_type: regex 397 | match_metric_type: counter 398 | name: "unknown_metric_counter" 399 | labels: 400 | hostname: "$1" 401 | name: "$2" 402 | type: "counter" 403 | 404 | - match: ([a-zA-Z0-9-]*[a-zA-Z0-9.]*\.net)\.(.*)$ 405 | match_type: regex 406 | match_metric_type: gauge 407 | name: "unknown_metric_gauge" 408 | labels: 409 | hostname: "$1" 410 | name: "$2" 411 | type: "gauge" 412 | 413 | - match: ([a-zA-Z0-9-]*[a-zA-Z0-9.]*\.net)\.(.*)$ 414 | match_type: regex 415 | match_metric_type: timer 416 | name: "unknown_metric_timer" 417 | labels: 418 | hostname: "$1" 419 | name: "$2" 420 | type: "timer" 421 | 422 | ### new "legacy" metrics that use the "dotted label" format 423 | - match: (^.*\..*$) 424 | match_type: regex 425 | match_metric_type: counter 426 | name: "unknown_raw_metric_counter" 427 | labels: 428 | name: "$1" 429 | type: "counter" 430 | 431 | - match: (^.*\..*$) 432 | match_type: regex 433 | match_metric_type: gauge 434 | name: "unknown_raw_metric_gauge" 435 | labels: 436 | name: "$1" 437 | type: "gauge" 438 | 439 | - match: (^.*\..*$) 440 | match_type: regex 441 | match_metric_type: timer 442 | name: "unknown_raw_metric_timer" 443 | labels: 444 | name: "$1" 445 | type: "timer" 446 | 447 | - match: (^.*\..*$) 448 | match_type: regex 449 | name: "unknown_raw_metric_other" 450 | labels: 451 | name: "$1" 452 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/swift/bench.conf: -------------------------------------------------------------------------------- 1 | [bench] 2 | # auth = http://localhost:8080/auth/v1.0 3 | # user = test:tester 4 | # key = testing 5 | # auth_version = 1.0 6 | # log-level = INFO 7 | # timeout = 10 8 | 9 | # You can configure PUT, GET, and DELETE concurrency independently or set all 10 | # three with "concurrency" 11 | # put_concurrency = 10 12 | # get_concurrency = 10 13 | # del_concurrency = 10 14 | # concurrency = 15 | 16 | # A space-sep list of files whose contents will be read and randomly chosen 17 | # as the body (object contents) for each PUT. 18 | # object_sources = 19 | 20 | # If object_sources is not set and lower_object_size != upper_object_size, 21 | # each PUT will randomly select an object size between the two values. Units 22 | # are bytes. 23 | # lower_object_size = 10 24 | # upper_object_size = 10 25 | 26 | # If object_sources is not set and lower_object_size == upper_object_size, 27 | # every object PUT will contain this many bytes. 28 | # object_size = 1 29 | 30 | # num_objects = 1000 31 | # num_gets = 10000 32 | # num_containers = 20 33 | 34 | # The base name for created containers. 35 | # container_name = (randomly-chosen uuid4) 36 | 37 | # The storage policy to use when creating containers 38 | # policy_name = gold 39 | 40 | # Should swift-bench benchmark DELETEing the created objects and then delete 41 | # all created containers? 42 | # delete = yes 43 | 44 | # Without use_proxy, swift-bench will talk directly to the backend Swift 45 | # servers. Doing that will require "url", "account", and at least one 46 | # "devices" entry. 47 | # use_proxy = yes 48 | 49 | # If use_proxy = yes, this will override any returned X-Storage-Url returned 50 | # by authenticaion (the account name will still be extracted from 51 | # X-Storage-Url though and may NOT be set with the "account" conf var). If 52 | # use_proxy = no, this setting is required and used as the X-Storage-Url when 53 | # deleting containers and as a source for IP and port for back-end Swift server 54 | # connections. The IP and port specified in this setting must have local 55 | # storage access to every device specified in "devices". 56 | # url = 57 | 58 | # Only used (and required) when use_proxy = no. 59 | # account = 60 | 61 | # A space-sep list of devices names; only relevant (and required) when 62 | # use_proxy = no. 63 | # devices = sdb1 64 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/swift/container-reconciler.conf.d/20_settings.conf: -------------------------------------------------------------------------------- 1 | [container-reconciler] 2 | 3 | [pipeline:main] 4 | pipeline = catch_errors proxy-logging cache proxy-server 5 | 6 | [app:proxy-server] 7 | use = egg:swift#proxy 8 | 9 | [filter:cache] 10 | use = egg:swift#memcache 11 | 12 | [filter:proxy-logging] 13 | use = egg:swift#proxy_logging 14 | 15 | [filter:catch_errors] 16 | use = egg:swift#catch_errors 17 | 18 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/swift/keymaster.conf: -------------------------------------------------------------------------------- 1 | [keymaster] 2 | active_root_secret_id = 2018 3 | # base64.encodestring(hashlib.md5('swift').hexdigest()) 4 | encryption_root_secret = ODE4MDU2ZGJkN2UyMDEyNDMyMDZiOWM3Y2Q4ODQ4MWM= 5 | # base64.encodestring(hashlib.md5('swift-1').hexdigest()) 6 | encryption_root_secret_2018 = YjQ0YmEyNzAyZDk1ZDk0YjJjMmM3NmFiNGRlZDlhMzg= 7 | # base64.encodestring(hashlib.md5('swift-3').hexdigest()) 8 | encryption_root_secret_2019 = YWVlZWYwY2ZmZmFlYzk3NmFjZjUyYTE5MWM1ZDY5YTI= 9 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/swift/object-expirer.conf.d/20_settings.conf: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | 3 | [object-expirer] 4 | 5 | [pipeline:main] 6 | pipeline = catch_errors cache proxy-logging proxy-server 7 | 8 | [app:proxy-server] 9 | use = egg:swift#proxy 10 | 11 | [filter:proxy-logging] 12 | use = egg:swift#proxy_logging 13 | 14 | [filter:cache] 15 | use = egg:swift#memcache 16 | 17 | [filter:catch_errors] 18 | use = egg:swift#catch_errors 19 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/systemd/system/grafana.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Grafana Server 3 | After=multi-user.target 4 | 5 | [Service] 6 | ExecStart=/usr/local/bin/grafana 7 | 8 | [Install] 9 | WantedBy=multi-user.target 10 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/systemd/system/prometheus.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Prometheus Server 3 | After=multi-user.target 4 | 5 | [Service] 6 | ExecStart=/usr/local/bin/prometheus \ 7 | --config.file="/etc/prometheus/prometheus.yaml" \ 8 | --storage.tsdb.path="/tmp/prom/data/" \ 9 | --storage.tsdb.retention.time=1d 10 | 11 | [Install] 12 | WantedBy=multi-user.target 13 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/systemd/system/pykmip-server.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=PyKMIP server 3 | After=multi-user.target 4 | 5 | [Service] 6 | ExecStart=/usr/local/bin/pykmip-server 7 | 8 | [Install] 9 | WantedBy=multi-user.target 10 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/etc/systemd/system/statsd_exporter@.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=StatsD Exporter Server #%I 3 | After=multi-user.target 4 | 5 | [Service] 6 | ExecStart=/usr/local/bin/statsd_exporter \ 7 | --web.listen-address=":910%i" \ 8 | --statsd.listen-udp=":912%i" \ 9 | --statsd.listen-tcp="" \ 10 | --statsd.mapping-config="/etc/prometheus/statsd_mapping.yaml" 11 | 12 | [Install] 13 | WantedBy=multi-user.target 14 | -------------------------------------------------------------------------------- /cookbooks/swift/files/default/home/nanorc: -------------------------------------------------------------------------------- 1 | set tabsize 4 2 | set tabstospaces 3 | set fill 79 4 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/ansible.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | [ 6 | "ansible", 7 | ].each do |pkg| 8 | execute "pip install #{pkg}" do 9 | command "pip install #{pkg}" 10 | end 11 | end 12 | 13 | [ 14 | "/etc/ansible", 15 | "/var/log/ansible", 16 | ].each do |dir| 17 | directory dir do 18 | owner node['username'] 19 | group node["username"] 20 | action :create 21 | end 22 | end 23 | 24 | [ 25 | 'hosts', 26 | 'ansible.cfg', 27 | ].each do |filename| 28 | cookbook_file "/etc/ansible/#{filename}" do 29 | source "etc/ansible/#{filename}" 30 | owner node["username"] 31 | group node["username"] 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/configs.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | # rsync 6 | 7 | template "/etc/rsyncd.conf" do 8 | source "etc/rsyncd.conf.erb" 9 | notifies :restart, 'service[rsync]' 10 | variables({ 11 | :username => node['username'], 12 | }) 13 | end 14 | 15 | if node['platform_version'] == '22.04' then 16 | execute "enable-rsync" do 17 | command "systemctl enable rsync.service" 18 | action :run 19 | end 20 | else 21 | execute "enable-rsync" do 22 | command "sed -i 's/ENABLE=false/ENABLE=true/' /etc/default/rsync" 23 | not_if "grep ENABLE=true /etc/default/rsync" 24 | action :run 25 | end 26 | end 27 | 28 | # per device rsync modules 29 | 30 | directory "/etc/rsyncd.d" do 31 | owner "vagrant" 32 | group "vagrant" 33 | action :create 34 | end 35 | 36 | ["container", "account"].each do |service| 37 | (1..node['disks']).each do |i| 38 | dev = "sdb#{i}" 39 | n = ((i - 1) % node['nodes']) + 1 40 | template "/etc/rsyncd.d/#{service}_#{dev}.conf" do 41 | source "/etc/rsyncd.d/rsync_disk.erb" 42 | owner "vagrant" 43 | group "vagrant" 44 | variables({ 45 | :service => service, 46 | :dev => dev, 47 | :n => n, 48 | }) 49 | end 50 | end 51 | end 52 | 53 | (1..[node['disks'], node['ec_disks']].max).each do |i| 54 | dev = "sdb#{i}" 55 | n = ((i - 1) % node['nodes']) + 1 56 | template "/etc/rsyncd.d/object_#{dev}.conf" do 57 | source "/etc/rsyncd.d/rsync_disk.erb" 58 | owner "vagrant" 59 | group "vagrant" 60 | variables({ 61 | :service => "object", 62 | :dev => "sdb#{i}", 63 | :n => n, 64 | }) 65 | end 66 | end 67 | 68 | # services 69 | 70 | [ 71 | "rsync", 72 | "memcached", 73 | "rsyslog", 74 | ].each do |daemon| 75 | service daemon do 76 | action :start 77 | end 78 | end 79 | 80 | # haproxy 81 | 82 | execute "create key" do 83 | command "openssl genpkey -algorithm EC -out saio.key " \ 84 | "-pkeyopt ec_paramgen_curve:prime256v1 " \ 85 | "-pkeyopt ec_param_enc:named_curve" 86 | #command "openssl genpkey -algorithm RSA -out saio.key " \ 87 | # "-pkeyopt rsa_keygen_bits:2048" 88 | cwd "/etc/ssl/private/" 89 | creates "/etc/ssl/private/saio.key" 90 | end 91 | 92 | template "/etc/ssl/private/saio.conf" do 93 | source "/etc/ssl/private/saio.conf.erb" 94 | variables({ 95 | :ip => node["ip"], 96 | :hostname => node["hostname"], 97 | }) 98 | end 99 | 100 | execute "create cert" do 101 | command "openssl req -x509 -days 365 -key saio.key " \ 102 | "-out saio.crt -config saio.conf" 103 | cwd "/etc/ssl/private/" 104 | creates "#{node['saio_crt_path']}" 105 | end 106 | 107 | execute "install cert" do 108 | command "mkdir -p /usr/local/share/ca-certificates/extra && " \ 109 | "cp #{node['saio_crt_path']} /usr/local/share/ca-certificates/extra/saio_ca.crt && " \ 110 | "update-ca-certificates" 111 | creates "/usr/local/share/ca-certificates/extra/saio_ca.crt" 112 | end 113 | 114 | # fix certifi (again?); we do this in the source.rb recipe (but only for the 115 | # benefit of bin/reinstall), during normal bring-up this is our first 116 | # opportunity to fix certifi 117 | execute "fix certifi" do 118 | command "cat #{node['saio_crt_path']} >> $(python3 -m certifi)" 119 | end 120 | 121 | execute "create pem" do 122 | command "cat saio.crt saio.key > saio.pem" 123 | cwd "/etc/ssl/private/" 124 | creates "/etc/ssl/private/saio.pem" 125 | end 126 | 127 | cookbook_file "/etc/haproxy/haproxy.cfg" do 128 | source "etc/haproxy/haproxy.cfg" 129 | notifies :restart, 'service[haproxy]' 130 | owner node['username'] 131 | group node['username'] 132 | end 133 | 134 | service "haproxy" do 135 | if node['ssl'] then 136 | action :start 137 | else 138 | action :stop 139 | end 140 | end 141 | 142 | # metrics pipeline 143 | 144 | directory "/etc/prometheus" do 145 | owner "vagrant" 146 | group "vagrant" 147 | action :create 148 | end 149 | 150 | [ 151 | "statsd_mapping.yaml", 152 | "prometheus.yaml", 153 | "prometheus-rules.yaml", 154 | ].each do |filename| 155 | cookbook_file "/etc/prometheus/#{filename}" do 156 | source "etc/prometheus/#{filename}" 157 | if filename == "statsd_mapping.yaml" then 158 | (0..5).each do |n| 159 | notifies :restart, "service[statsd_exporter@#{n}]" 160 | end 161 | else 162 | notifies :restart, 'service[prometheus]' 163 | end 164 | owner node['username'] 165 | group node['username'] 166 | end 167 | end 168 | 169 | service "prometheus" do 170 | action (if node["statsd_exporter"] then [:enable, :start] else :stop end) 171 | end 172 | (0..5).each do |n| 173 | service "statsd_exporter@#{n}" do 174 | action (if node["statsd_exporter"] then [:enable, :start] else :stop end) 175 | end 176 | end 177 | 178 | # swift 179 | 180 | directory "/etc/swift" do 181 | owner node['username'] 182 | group node["username"] 183 | action :create 184 | end 185 | 186 | template "/etc/rc.local" do 187 | # Make /var/run/swift/ survive reboots 188 | source "etc/rc.local.erb" 189 | mode 0755 190 | variables({ 191 | :username => node['username'], 192 | }) 193 | end 194 | 195 | [ 196 | 'bench.conf', 197 | 'keymaster.conf', 198 | ].each do |filename| 199 | cookbook_file "/etc/swift/#{filename}" do 200 | source "etc/swift/#{filename}" 201 | owner node["username"] 202 | group node["username"] 203 | end 204 | end 205 | 206 | [ 207 | 'base.conf-template', 208 | 'dispersion.conf', 209 | 'container-sync-realms.conf', 210 | 'test.conf', 211 | 'swift.conf', 212 | ].each do |filename| 213 | template "/etc/swift/#{filename}" do 214 | source "/etc/swift/#{filename}.erb" 215 | owner node["username"] 216 | group node["username"] 217 | variables({}.merge(node)) 218 | end 219 | end 220 | 221 | # proxies 222 | 223 | directory "/etc/swift/proxy-server" do 224 | owner node["username"] 225 | group node["username"] 226 | end 227 | 228 | template "/etc/swift/proxy-server/default.conf-template" do 229 | source "etc/swift/proxy-server/default.conf-template.erb" 230 | owner node["username"] 231 | group node["username"] 232 | variables({ 233 | :disable_encryption => ! node['encryption'], 234 | }) 235 | end 236 | 237 | [ 238 | "proxy-server", 239 | "proxy-noauth", 240 | ].each do |proxy| 241 | proxy_conf_dir = "etc/swift/proxy-server/#{proxy}.conf.d" 242 | directory proxy_conf_dir do 243 | owner node["username"] 244 | group node["username"] 245 | action :create 246 | end 247 | link "/#{proxy_conf_dir}/00_base.conf" do 248 | to "/etc/swift/base.conf-template" 249 | owner node["username"] 250 | group node["username"] 251 | end 252 | link "/#{proxy_conf_dir}/10_default.conf" do 253 | to "/etc/swift/proxy-server/default.conf-template" 254 | owner node["username"] 255 | group node["username"] 256 | end 257 | if node['kmip'] then 258 | keymaster_pipeline = 'kmip_keymaster' 259 | else 260 | keymaster_pipeline = 'keymaster' 261 | end 262 | template "/#{proxy_conf_dir}/20_settings.conf" do 263 | source "#{proxy_conf_dir}/20_settings.conf.erb" 264 | owner node["username"] 265 | group node["username"] 266 | variables({ 267 | :ssl => node['ssl'], 268 | :keymaster_pipeline => keymaster_pipeline, 269 | :nvratelimit_pipeline => node['nvratelimit'] ? 'nvratelimit' : '', 270 | :statsd_exporter => node["statsd_exporter"], 271 | }) 272 | end 273 | end 274 | 275 | (1..node['nodes']).each do |i| 276 | template "/etc/swift/node#{i}.conf-template" do 277 | source "/etc/swift/node.conf-template.erb" 278 | owner node["username"] 279 | group node["username"] 280 | variables({ 281 | :srv_path => "/srv/node#{i}", 282 | :bind_ip => "127.0.0.#{i}", 283 | :statsd_port => "912#{i}", 284 | :recon_cache_path => "/var/cache/swift/node#{i}", 285 | :statsd_exporter => node["statsd_exporter"], 286 | }) 287 | end 288 | end 289 | 290 | [:object, :container, :account].each_with_index do |service, p| 291 | service_dir = "etc/swift/#{service}-server" 292 | directory "/#{service_dir}" do 293 | owner node["username"] 294 | group node["username"] 295 | action :create 296 | end 297 | template "/#{service_dir}/server.conf-template" do 298 | source "#{service_dir}/server.conf-template.erb" 299 | owner node["username"] 300 | group node["username"] 301 | variables({ 302 | :servers_per_port => node['servers_per_port'], 303 | :replication_server => !node["replication_servers"], 304 | }) 305 | end 306 | if node["replication_servers"] then 307 | template "/#{service_dir}/replication-server.conf-template" do 308 | source "#{service_dir}/server.conf-template.erb" 309 | owner node["username"] 310 | group node["username"] 311 | variables({ 312 | :servers_per_port => node['servers_per_port'], 313 | :replication_server => true, 314 | }) 315 | end 316 | else 317 | file "/#{service_dir}/replication-server.conf-template" do 318 | action :delete 319 | end 320 | end 321 | template "/#{service_dir}/replication-daemons.conf-template" do 322 | source "#{service_dir}/replication.conf-template.erb" 323 | owner node["username"] 324 | group node["username"] 325 | variables({ 326 | :auto_shard => node['container_auto_shard'], 327 | :sync_method => node['object_sync_method'], 328 | }) 329 | end 330 | (1..node['nodes']).each do |i| 331 | bind_port = 6000 + 10 * i + p 332 | replication_bind_port = 6000 + 10 * (i + node['nodes']) + p 333 | if service == :object && node['servers_per_port'] > 0 then 334 | # These config settings shouldn't really matter in the server-per-port 335 | # scenario, but they should probably at least be equal to one of the actual 336 | # ports in the ring. 337 | bind_port = 6000 + 10 * i + 6 338 | replication_bind_port = 6000 + 10 * (i + node['nodes']) + 6 339 | end 340 | server_conf_dir = "#{service_dir}/#{i}.conf.d" 341 | replication_conf_dir = "#{service_dir}/#{i + node['nodes']}-replication.conf.d" 342 | directory "/#{server_conf_dir}" do 343 | owner node["username"] 344 | group node["username"] 345 | end 346 | link "/#{server_conf_dir}/00_base.conf" do 347 | to "/etc/swift/base.conf-template" 348 | owner node["username"] 349 | group node["username"] 350 | end 351 | link "/#{server_conf_dir}/10_node.conf" do 352 | to "/etc/swift/node#{i}.conf-template" 353 | owner node["username"] 354 | group node["username"] 355 | end 356 | link "/#{server_conf_dir}/20_server.conf" do 357 | to "/#{service_dir}/server.conf-template" 358 | owner node["username"] 359 | group node["username"] 360 | end 361 | template "/#{server_conf_dir}/30_settings.conf" do 362 | source "#{service_dir}/settings.conf.erb" 363 | owner node["username"] 364 | group node["username"] 365 | variables({ 366 | :bind_port => bind_port, 367 | :include_replication_settings => !node["replication_servers"], 368 | }) 369 | end 370 | if node["replication_servers"] then 371 | file "/#{server_conf_dir}/40_replication.conf" do 372 | action :delete 373 | end 374 | directory "/#{replication_conf_dir}" do 375 | owner node["username"] 376 | group node["username"] 377 | end 378 | link "/#{replication_conf_dir}/00_base.conf" do 379 | to "/etc/swift/base.conf-template" 380 | owner node["username"] 381 | group node["username"] 382 | end 383 | link "/#{replication_conf_dir}/10_node.conf" do 384 | to "/etc/swift/node#{i}.conf-template" 385 | owner node["username"] 386 | group node["username"] 387 | end 388 | link "/#{replication_conf_dir}/20_server.conf" do 389 | to "/#{service_dir}/replication-server.conf-template" 390 | owner node["username"] 391 | group node["username"] 392 | end 393 | template "/#{replication_conf_dir}/30_settings.conf" do 394 | source "#{service_dir}/settings.conf.erb" 395 | owner node["username"] 396 | group node["username"] 397 | variables({ 398 | :bind_port => replication_bind_port, 399 | :include_replication_settings => true, 400 | }) 401 | end 402 | link "/#{replication_conf_dir}/40_replication.conf" do 403 | to "/#{service_dir}/replication-daemons.conf-template" 404 | owner node["username"] 405 | group node["username"] 406 | end 407 | else 408 | directory "/#{replication_conf_dir}" do 409 | action :delete 410 | recursive true 411 | end 412 | link "/#{server_conf_dir}/40_replication.conf" do 413 | to "/#{service_dir}/replication-daemons.conf-template" 414 | owner node["username"] 415 | group node["username"] 416 | end 417 | end 418 | end 419 | end 420 | 421 | # object-expirer 422 | directory "/etc/swift/object-expirer.conf.d" do 423 | owner node["username"] 424 | group node["username"] 425 | action :create 426 | end 427 | link "/etc/swift/object-expirer.conf.d/00_base.conf" do 428 | to "/etc/swift/base.conf-template" 429 | owner node["username"] 430 | group node["username"] 431 | end 432 | cookbook_file "/etc/swift/object-expirer.conf.d/20_settings.conf" do 433 | source "etc/swift/object-expirer.conf.d/20_settings.conf" 434 | owner node["username"] 435 | group node["username"] 436 | end 437 | 438 | # container-reconciler 439 | directory "/etc/swift/container-reconciler.conf.d" do 440 | owner node["username"] 441 | group node["username"] 442 | action :create 443 | end 444 | link "/etc/swift/container-reconciler.conf.d/00_base.conf" do 445 | to "/etc/swift/base.conf-template" 446 | owner node["username"] 447 | group node["username"] 448 | end 449 | cookbook_file "/etc/swift/container-reconciler.conf.d/20_settings.conf" do 450 | source "etc/swift/container-reconciler.conf.d/20_settings.conf" 451 | owner node["username"] 452 | group node["username"] 453 | end 454 | 455 | # internal-client.conf 456 | if node['kmip'] then 457 | keymaster_pipeline = 'kmip_keymaster' 458 | else 459 | keymaster_pipeline = 'keymaster' 460 | end 461 | template "/etc/swift/internal-client.conf" do 462 | source "etc/swift/internal-client.conf.erb" 463 | owner node["username"] 464 | owner node["username"] 465 | variables({ 466 | :disable_encryption => ! node['encryption'], 467 | :keymaster_pipeline => keymaster_pipeline, 468 | }) 469 | end 470 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/data.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | # setup up some disk 6 | 7 | [ 8 | "/var/lib/swift", 9 | "/mnt/swift-disk", 10 | ].each do |d| 11 | directory d do 12 | action :create 13 | end 14 | end 15 | 16 | if node['ec_policy'].empty? then 17 | num_disks = node['disks'] 18 | else 19 | num_disks = [node['disks'], node['ec_disks']].max 20 | end 21 | 22 | def make_disk(disk_file, mount_path, size="#{node['loopback_gb']}GB") 23 | execute "create sparse file #{disk_file}" do 24 | command "truncate -s #{size} #{disk_file}" 25 | creates "#{disk_file}" 26 | action :run 27 | end 28 | 29 | execute "create file system" do 30 | command "mkfs.xfs #{disk_file}" 31 | not_if "xfs_admin -l #{disk_file}" 32 | action :run 33 | end 34 | 35 | directory mount_path do 36 | owner 'root' 37 | group 'root' 38 | mode '0755' 39 | recursive true 40 | action :create 41 | end 42 | 43 | execute "update fstab for #{disk_file}" do 44 | command "echo '#{disk_file} #{mount_path} xfs " \ 45 | "loop,noatime 0 0' >> /etc/fstab" 46 | not_if "grep #{mount_path} /etc/fstab" 47 | action :run 48 | end 49 | 50 | execute "mount" do 51 | command "mount #{mount_path}" 52 | not_if "mountpoint #{mount_path}" 53 | end 54 | 55 | # Fix perms on mounted dir 56 | directory mount_path do 57 | owner node["username"] 58 | group node["username"] 59 | mode '0775' 60 | end 61 | end 62 | 63 | (1..num_disks).each do |i| 64 | j = ((i - 1) % node['nodes']) + 1 65 | make_disk "/var/lib/swift/disk#{i}", "/srv/node#{j}/sdb#{i}" 66 | end 67 | 68 | # for unittest xfs scratch 69 | make_disk "/var/lib/swift/tmp-disk", "/mnt/tmp", "400MB" 70 | 71 | # run dirs 72 | 73 | [ 74 | "/var/run/swift", 75 | "/var/cache/swift", 76 | ].each do |d| 77 | directory d do 78 | owner node["username"] 79 | group node["username"] 80 | action :create 81 | end 82 | end 83 | 84 | (1..node['nodes']).each do |i| 85 | recon_cache_path = "/var/cache/swift/node#{i}" 86 | directory recon_cache_path do 87 | owner node["username"] 88 | group node["username"] 89 | recursive true 90 | end 91 | end 92 | 93 | # make vagrant able to read /var/log/syslog 94 | group "adm" do 95 | action :modify 96 | members node["username"] 97 | append true 98 | end 99 | 100 | # make vagrant able to docker 101 | group "docker" do 102 | action :modify 103 | members node["username"] 104 | append true 105 | end 106 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | include_recipe "swift::setup" 6 | include_recipe "swift::statsd_exporter" 7 | include_recipe "swift::source" 8 | include_recipe "swift::data" 9 | include_recipe "swift::configs" 10 | include_recipe "swift::pykmip" 11 | include_recipe "swift::rings" 12 | include_recipe "swift::ansible" 13 | 14 | # start main 15 | 16 | execute "startmain" do 17 | command "swift-init start main" 18 | user node['username'] 19 | group node["username"] 20 | end 21 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/pykmip.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | if not node['kmip'] then 6 | # TODO: more cleanup? 7 | service 'pykmip-server' do 8 | action [:disable, :stop] 9 | end 10 | return 11 | end 12 | 13 | PYKMIP_DIR = "/etc/pykmip" 14 | 15 | 16 | [ 17 | PYKMIP_DIR, 18 | "#{PYKMIP_DIR}/certs", 19 | "#{PYKMIP_DIR}/policies", 20 | "/var/lib/pykmip", 21 | "/var/log/pykmip", 22 | ].each do |dir| 23 | directory dir do 24 | owner node['username'] 25 | group node["username"] 26 | action :create 27 | end 28 | end 29 | 30 | 31 | # keys and certs 32 | 33 | CA_KEY = "#{PYKMIP_DIR}/certs/ca.key" 34 | execute "create certificate authority key" do 35 | cwd PYKMIP_DIR 36 | user node['username'] 37 | group node["username"] 38 | # creates CA_KEY 39 | command "openssl genrsa -out #{CA_KEY} 2048" 40 | end 41 | 42 | CA_CRT = "#{PYKMIP_DIR}/certs/ca.crt" 43 | execute "create self-signed certificate authority crt" do 44 | cwd PYKMIP_DIR 45 | user node['username'] 46 | group node["username"] 47 | # creates CA_CRT 48 | command "openssl req -new -x509 -key #{CA_KEY} -days 3650 " \ 49 | "-out #{CA_CRT} -subj '/CN=ca.example.com'" 50 | end 51 | 52 | SERVER_KEY = "#{PYKMIP_DIR}/certs/kmip-server.key" 53 | execute "create pykmip server key" do 54 | cwd PYKMIP_DIR 55 | user node['username'] 56 | group node["username"] 57 | # creates SERVER_KEY 58 | command "openssl genrsa -out #{SERVER_KEY} 2048" 59 | end 60 | 61 | SERVER_CSR = "#{PYKMIP_DIR}/certs/kmip-server.csr" 62 | execute "create pykmip server csr" do 63 | cwd PYKMIP_DIR 64 | user node['username'] 65 | group node["username"] 66 | # creates SERVER_CSR 67 | command "openssl req -new -key #{SERVER_KEY} " \ 68 | "-out #{SERVER_CSR} -subj '/CN=kmip-server.example.com'" 69 | end 70 | 71 | SERVER_CRT = "#{PYKMIP_DIR}/certs/kmip-server.crt" 72 | execute "creates pykmip server crt" do 73 | cwd PYKMIP_DIR 74 | user node['username'] 75 | group node["username"] 76 | # creates SERVER_CRT 77 | command "openssl x509 -req -CA #{CA_CRT} -CAkey #{CA_KEY} -CAcreateserial " \ 78 | "-in #{SERVER_CSR} -out #{SERVER_CRT} -days 3650" 79 | end 80 | 81 | CLIENT_KEY = "#{PYKMIP_DIR}/certs/kmip-client.key" 82 | execute "create pykmip client key" do 83 | cwd PYKMIP_DIR 84 | user node['username'] 85 | group node["username"] 86 | # creates CLIENT_KEY 87 | command "openssl genrsa -out #{CLIENT_KEY} 2048" 88 | end 89 | 90 | CLIENT_CSR = "#{PYKMIP_DIR}/certs/kmip-client.csr" 91 | execute "create pykmip client csr" do 92 | cwd PYKMIP_DIR 93 | user node['username'] 94 | group node["username"] 95 | # creates CLIENT_CSR 96 | command "openssl req -new -key #{CLIENT_KEY} " \ 97 | "-out #{CLIENT_CSR} -subj '/CN=kmip-client.example.com'" 98 | end 99 | 100 | CLIENT_CRT = "#{PYKMIP_DIR}/certs/kmip-client.crt" 101 | execute "creates pykmip client crt" do 102 | cwd PYKMIP_DIR 103 | user node['username'] 104 | group node["username"] 105 | # creates CLIENT_CRT 106 | command "openssl x509 -req -CA #{CA_CRT} -CAkey #{CA_KEY} -CAcreateserial " \ 107 | "-in #{CLIENT_CSR} -out #{CLIENT_CRT} -days 3650" 108 | end 109 | 110 | 111 | # trust ca 112 | 113 | execute "install ca" do 114 | command "cp #{CA_CRT} /usr/local/share/ca-certificates/ca.crt" 115 | end 116 | 117 | execute "trust ca" do 118 | command "sudo update-ca-certificates" 119 | end 120 | 121 | 122 | # configs 123 | 124 | template "#{PYKMIP_DIR}/server.conf" do 125 | source "etc/pykmip/server.conf.erb" 126 | owner node["username"] 127 | group node["username"] 128 | variables({ 129 | :ca_crt => CA_CRT, 130 | :server_key => SERVER_KEY, 131 | :server_crt => SERVER_CRT, 132 | }) 133 | end 134 | 135 | template "#{PYKMIP_DIR}/pykmip.conf" do 136 | source "etc/pykmip/pykmip.conf.erb" 137 | owner node["username"] 138 | group node["username"] 139 | variables({ 140 | :ca_crt => CA_CRT, 141 | :client_key => CLIENT_KEY, 142 | :client_crt => CLIENT_CRT, 143 | }) 144 | end 145 | 146 | template "/etc/swift/kmip_keymaster.conf" do 147 | source "etc/swift/kmip_keymaster.conf.erb" 148 | owner node["username"] 149 | group node["username"] 150 | variables({ 151 | :client_key => CLIENT_KEY, 152 | :client_crt => CLIENT_CRT, 153 | :ca_crt => CA_CRT, 154 | }) 155 | end 156 | 157 | 158 | # install 159 | 160 | execute "install pykmip" do 161 | command "pip install pykmip --upgrade" 162 | if not node['full_reprovision'] 163 | creates "/usr/local/bin/pykmip-server" 164 | end 165 | end 166 | 167 | 168 | # systemd unit file 169 | 170 | cookbook_file "/etc/systemd/system/pykmip-server.service" do 171 | source "etc/systemd/system/pykmip-server.service" 172 | end 173 | 174 | service 'pykmip-server' do 175 | action [:enable, :restart, :start] 176 | end 177 | 178 | 179 | # add key 180 | 181 | execute "add key" do 182 | command "/vagrant/bin/kmipkey" 183 | end 184 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/rings.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | # rings 6 | 7 | ["container", "account"].each_with_index do |service, p| 8 | execute "#{service}.builder-create" do 9 | command "swift-ring-builder #{service}.builder create " \ 10 | "#{node['part_power']} #{node['replicas']} 1" 11 | user node['username'] 12 | group node["username"] 13 | creates "/etc/swift/#{service}.builder" 14 | cwd "/etc/swift" 15 | end 16 | (1..node['disks']).each do |i| 17 | n_idx = ((i - 1) % node['nodes']) + 1 18 | z = ((n_idx - 1) % node['zones']) + 1 19 | r = ((z - 1) % node['regions']) + 1 20 | dev = "sdb#{i}" 21 | ip = "127.0.0.#{n_idx}" 22 | port = 6000 + 10 * n_idx + (p + 1) 23 | replication_port = 6000 + 10 * (n_idx + node['nodes']) + (p + 1) 24 | dsl = "r#{r}z#{z}-#{ip}:#{port}/#{dev}" 25 | if node['replication_servers'] then 26 | dsl = "r#{r}z#{z}-#{ip}:#{port}R#{ip}:#{replication_port}/#{dev}" 27 | end 28 | execute "#{service}.builder-add-#{dev}" do 29 | command "swift-ring-builder #{service}.builder add " \ 30 | "#{dsl} 1 && rm -f /etc/swift/#{service}.ring.gz || true" 31 | user node['username'] 32 | group node["username"] 33 | not_if "swift-ring-builder /etc/swift/#{service}.builder search #{dsl}" 34 | cwd "/etc/swift" 35 | end 36 | end 37 | execute "#{service}.builder-rebalance" do 38 | command "swift-ring-builder /etc/swift/#{service}.builder rebalance -f" 39 | user node['username'] 40 | group node["username"] 41 | cwd "/etc/swift" 42 | returns [0, 1] # Allow EXIT_WARNING 43 | end 44 | end 45 | 46 | node['storage_policies'].each_with_index do |name, p| 47 | service = "object" 48 | if p >= 1 then 49 | service += "-#{p}" 50 | end 51 | if name == node['ec_policy'] then 52 | replicas = node['ec_replicas'] * node['ec_duplication'] 53 | num_disks = node['ec_disks'] 54 | else 55 | replicas = node['replicas'] 56 | num_disks = node['disks'] 57 | end 58 | execute "#{service}.builder-create" do 59 | command "swift-ring-builder #{service}.builder create " \ 60 | "#{node['part_power']} #{replicas} 1" 61 | user node['username'] 62 | group node["username"] 63 | creates "/etc/swift/#{service}.builder" 64 | cwd "/etc/swift" 65 | end 66 | (1..num_disks).each do |i| 67 | n_idx = ((i - 1) % node['nodes']) + 1 68 | z = ((n_idx - 1) % node['zones']) + 1 69 | r = ((z - 1) % node['regions']) + 1 70 | dev = "sdb#{i}" 71 | ip = "127.0.0.#{n_idx}" 72 | port = 6000 + 10 * n_idx 73 | replication_port = 6000 + 10 * (n_idx + node['nodes']) 74 | if node['servers_per_port'] > 0 then 75 | # Range ports per disk per node from 60j6 - 60j9 76 | # NOTE: this only supports DISKS <= 4 * NODES 77 | p = 5 + (i / Float(node['nodes'])).ceil.to_int 78 | port = 6000 + 10 * n_idx + p 79 | replication_port = 6000 + 10 * (n_idx + node['nodes']) + p 80 | end 81 | dsl = "r#{r}z#{z}-#{ip}:#{port}/#{dev}" 82 | if node['replication_servers'] then 83 | dsl = "r#{r}z#{z}-#{ip}:#{port}R#{ip}:#{replication_port}/#{dev}" 84 | end 85 | execute "#{service}.builder-add-#{dev}" do 86 | command "swift-ring-builder #{service}.builder add " \ 87 | "#{dsl} 1 && rm -f /etc/swift/#{service}.ring.gz || true" 88 | user node['username'] 89 | group node["username"] 90 | not_if "swift-ring-builder /etc/swift/#{service}.builder search /#{dsl}" 91 | cwd "/etc/swift" 92 | end 93 | end 94 | execute "#{service}.builder-rebalance" do 95 | command "swift-ring-builder /etc/swift/#{service}.builder rebalance -f" 96 | user node['username'] 97 | group node["username"] 98 | cwd "/etc/swift" 99 | returns [0, 1] # Allow EXIT_WARNING 100 | end 101 | end 102 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/setup.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | execute "clean-up" do 6 | command "rm /home/#{node['username']}/postinstall.sh || true" 7 | end 8 | 9 | execute 'ensure ssh directory exists' do 10 | command "mkdir -p ~#{node['username']}/.ssh" 11 | end 12 | 13 | if node['extra_key'] then 14 | keys_file = "~#{node['username']}/.ssh/authorized_keys" 15 | execute "add_extra_key" do 16 | command "echo '#{node['extra_key']}' >> #{keys_file}" 17 | not_if "grep -q '#{node['extra_key']}' #{keys_file}" 18 | end 19 | end 20 | 21 | # deadsnakes for all the pythons 22 | package "software-properties-common" do 23 | action :install 24 | not_if "which add-apt-repository" 25 | end 26 | 27 | execute "deadsnakes key" do 28 | command "sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys" 29 | action :run 30 | not_if "sudo apt-key list | grep 'Launchpad PPA for deadsnakes'" 31 | end 32 | 33 | execute "add repo" do 34 | command "sudo add-apt-repository ppa:deadsnakes/ppa" 35 | end 36 | 37 | execute "apt-get-update" do 38 | command "apt-get update && touch /tmp/.apt-get-update" 39 | if not node['full_reprovision'] 40 | creates "/tmp/.apt-get-update" 41 | end 42 | action :run 43 | end 44 | 45 | systemd_unit "multipathd" do 46 | # focal boxes generate a lot of useless logs with this guy running 47 | action [:disable, :stop] 48 | end 49 | 50 | # system packages 51 | required_packages = [ 52 | "libssl-dev", # libssl-dev is required for building wheels from the cryptography package in swift. 53 | "curl", "gcc", "memcached", "rsync", "sqlite3", "xfsprogs", "git", "build-essential", 54 | "libffi-dev", "libxml2-dev", "libxml2", "libxslt1-dev", "zlib1g-dev", "autoconf", "libtool", 55 | "haproxy", "docker-compose", "rclone", 56 | ] 57 | 58 | # common python versions 59 | required_packages += [ 60 | # most of time these come from deadsnakes 61 | "python3.7", "python3.7-distutils", 62 | "python3.8", "python3.8-distutils", 63 | "python3.9", "python3.9-distutils", 64 | "python3.10", 65 | "python3.11", 66 | "python3.12", 67 | "python3.13", # edge of technology! 68 | # python3 will be redundant with distro version, -dev is needed for pyeclib 69 | "python3", "python3-dev", 70 | ] 71 | 72 | # only focal has the *really* old py3 73 | if node['platform_version'].to_i <= 20 then 74 | required_packages += [ 75 | "python3.6", "python3.6-distutils", 76 | ] 77 | end 78 | 79 | # no-no packages (PIP rules this vm, most system packages are all out-of-date anyway) 80 | unrequired_packages = [ 81 | "python3-pip", "python3-pbr", "python3-setuptools", 82 | "python3-openssl", "python3-certifi", 83 | "python3-requests", "python3-urllib3", 84 | ] 85 | unrequired_packages.each do |pkg| 86 | package pkg do 87 | action :purge 88 | end 89 | end 90 | 91 | # good-good packages (do the install after purge) 92 | extra_packages = node['extra_packages'] 93 | (required_packages + extra_packages).each do |pkg| 94 | package pkg do 95 | action :install 96 | end 97 | end 98 | 99 | # see https://peps.python.org/pep-0668/ 100 | file 'break system python' do 101 | path "/etc/pip.conf" 102 | content <<-EOF 103 | [global] 104 | root-user-action = ignore 105 | break-system-packages = true 106 | EOF 107 | end 108 | 109 | # the less system packages the better, we install all python stuff with pip 110 | bash 'install pip' do 111 | code <<-EOF 112 | set -o pipefail 113 | curl "https://bootstrap.pypa.io/get-pip.py" | /usr/bin/env python3 114 | EOF 115 | if not node['full_reprovision'] 116 | not_if "which pip" 117 | end 118 | end 119 | 120 | # install pip packages 121 | 122 | [ 123 | "s3cmd", 124 | "awscli-plugin-endpoint", 125 | ].each do |pkg| 126 | execute "pip install #{pkg}" do 127 | command "pip install #{pkg}" 128 | end 129 | end 130 | 131 | # this works around some PBR/git interaction 132 | cookbook_file "/etc/gitconfig" do 133 | source "etc/gitconfig" 134 | owner node['username'] 135 | group node['username'] 136 | end 137 | 138 | # setup environment 139 | 140 | profile_file = "/home/#{node['username']}/.profile" 141 | 142 | execute "update-path" do 143 | command "echo 'export PATH=/vagrant/bin:$PATH' >> #{profile_file}" 144 | not_if "grep /vagrant/bin #{profile_file}" 145 | action :run 146 | end 147 | 148 | [ 149 | "/vagrant/.functions.sh", 150 | ].each do |filename| 151 | execute "source-#{filename}" do 152 | command "echo 'source #{filename}' >> #{profile_file}" 153 | not_if "grep 'source #{filename}' #{profile_file}" 154 | end 155 | end 156 | 157 | cookbook_file "/home/#{node['username']}/.nanorc" do 158 | source "home/nanorc" 159 | owner node['username'] 160 | group node['username'] 161 | end 162 | 163 | 164 | # swift command line env setup 165 | 166 | { 167 | "ST_AUTH" => node['auth_uri'], 168 | "ST_USER" => "test:tester", 169 | "ST_KEY" => "testing", 170 | "OS_AUTH_URL" => "http://#{node['hostname']}:8080/auth/v1.0", 171 | "OS_USERNAME" => "test:tester", 172 | "OS_PASSWORD" => "testing", 173 | }.each do |var, value| 174 | execute "swift-env-#{var}" do 175 | command "echo 'export #{var}=#{value}' >> #{profile_file}" 176 | not_if "grep #{var} #{profile_file} && " \ 177 | "sed '/#{var}/c\\export #{var}=#{value}' -i #{profile_file}" 178 | action :run 179 | end 180 | end 181 | 182 | 183 | # s3cmd setup 184 | 185 | template "/home/#{node['username']}/.s3cfg" do 186 | source "/home/s3cfg.erb" 187 | owner node['username'] 188 | group node['username'] 189 | mode 0700 190 | variables({ 191 | :ssl => node['ssl'], 192 | }) 193 | end 194 | 195 | # awscli setup 196 | 197 | directory "/home/#{node['username']}/.aws" do 198 | owner node['username'] 199 | group node['username'] 200 | mode 0700 201 | action :create 202 | end 203 | template "/home/#{node['username']}/.aws/config" do 204 | source "/home/aws/config.erb" 205 | owner node['username'] 206 | group node['username'] 207 | mode 0700 208 | variables({ 209 | :base_uri => node['base_uri'], 210 | }) 211 | end 212 | template "/home/#{node['username']}/.aws/credentials" do 213 | source "/home/aws/credentials.erb" 214 | owner node['username'] 215 | group node['username'] 216 | mode 0700 217 | end 218 | 219 | execute "enable bash completer for awscli" do 220 | command "ln -s $(which aws_bash_completer) /etc/bash_completion.d/" 221 | creates "/etc/bash_completion.d/aws_bash_completer" 222 | end 223 | 224 | # rclone setup 225 | # ~/.config/rclone/rclone.conf 226 | directory "/home/#{node['username']}/.config/rclone" do 227 | owner node['username'] 228 | group node['username'] 229 | recursive true 230 | mode 0700 231 | action :create 232 | end 233 | template "/home/#{node['username']}/.config/rclone/rclone.conf" do 234 | source "/home/rclone/rclone.erb" 235 | owner node['username'] 236 | group node['username'] 237 | mode 0700 238 | variables({ 239 | :ssl => node['ssl'], 240 | :hostname => node['hostname'], 241 | :base_uri => node['base_uri'], 242 | :auth_uri => node['auth_uri'], 243 | }) 244 | end 245 | 246 | # other useful env vars 247 | 248 | { 249 | "SOURCE_ROOT" => "#{node['source_root']}", 250 | "NOSE_INCLUDE_EXE" => "true", 251 | "TMPDIR" => "/mnt/tmp", 252 | }.each do |var, value| 253 | execute "swift-env-#{var}" do 254 | command "echo 'export #{var}=#{value}' >> #{profile_file}" 255 | not_if "grep #{var} #{profile_file} && " \ 256 | "sed '/#{var}/c\\export #{var}=#{value}' -i #{profile_file}" 257 | action :run 258 | end 259 | end 260 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/source.rb: -------------------------------------------------------------------------------- 1 | # 2 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 3 | #SPDX-License-Identifier: Apache-2.0 4 | 5 | # ensure source_root 6 | 7 | directory "#{node['source_root']}" do 8 | owner node["username"] 9 | group node["username"] 10 | action :create 11 | end 12 | 13 | # python install 14 | 15 | execute "git python-swiftclient" do 16 | cwd "#{node['source_root']}" 17 | command "git clone -b #{node['swiftclient_repo_branch']} #{node['swiftclient_repo']}" 18 | user node['username'] 19 | group node["username"] 20 | creates "#{node['source_root']}/python-swiftclient" 21 | action :run 22 | end 23 | 24 | execute "git swift-bench" do 25 | cwd "#{node['source_root']}" 26 | command "git clone -b #{node['swift_bench_repo_branch']} #{node['swift_bench_repo']}" 27 | user node['username'] 28 | group node["username"] 29 | creates "#{node['source_root']}/swift-bench" 30 | action :run 31 | end 32 | 33 | execute "git swift" do 34 | cwd "#{node['source_root']}" 35 | command "git clone -b #{node['swift_repo_branch']} #{node['swift_repo']}" 36 | user node['username'] 37 | group node["username"] 38 | creates "#{node['source_root']}/swift" 39 | action :run 40 | end 41 | 42 | execute "git liberasurecode" do 43 | cwd "#{node['source_root']}" 44 | command "git clone -b #{node['liberasurecode_repo_branch']} #{node['liberasurecode_repo']}" 45 | user node['username'] 46 | group node["username"] 47 | creates "#{node['source_root']}/liberasurecode" 48 | action :run 49 | end 50 | 51 | execute "git pyeclib" do 52 | cwd "#{node['source_root']}" 53 | command "git clone -b #{node['pyeclib_repo_branch']} #{node['pyeclib_repo']}" 54 | user node['username'] 55 | group node["username"] 56 | creates "#{node['source_root']}/pyeclib" 57 | action :run 58 | end 59 | 60 | 61 | execute "fix semantic_version error from testtools" do 62 | command "pip install --upgrade testtools" 63 | end 64 | 65 | execute "liberasurecode-install" do 66 | cwd "#{node['source_root']}/liberasurecode" 67 | command "./autogen.sh && " \ 68 | "./configure && " \ 69 | "make && " \ 70 | "make install && " \ 71 | "ldconfig" 72 | if not node['full_reprovision'] 73 | creates "/usr/local/lib/liberasurecode.so.1.2.0" 74 | end 75 | # avoid /opt/chef/embedded/bin - related to chef/chef-dk#313 76 | environment 'PATH' => "/usr/bin:#{ENV['PATH']}" 77 | action :run 78 | end 79 | 80 | execute "python-pyeclib-install" do 81 | cwd "#{node['source_root']}/pyeclib" 82 | command "pip install -e . && pip install -r test-requirements.txt" 83 | action :run 84 | end 85 | 86 | execute "python-swiftclient-install" do 87 | cwd "#{node['source_root']}/python-swiftclient" 88 | command "pip install -e . && pip install --ignore-installed -r test-requirements.txt" 89 | action :run 90 | end 91 | 92 | # since swiftclient forces cert reinstall; we do this now 93 | # N.B. the saio_crt_path is coupled with "create cert" task in configs.rb 94 | # yes, we create this file even if you have node['ssl'] == false 95 | execute "fix certifi" do 96 | only_if { ::File.exist?(node['saio_crt_path']) } 97 | command "cat #{node['saio_crt_path']} >> $(python3 -m certifi)" 98 | end 99 | 100 | execute "swift-bench-install" do 101 | cwd "#{node['source_root']}/swift-bench" 102 | # swift-bench has an old version of hacking in the test requirements, 103 | # seems to pull back pbr to 0.11 and break everything; not installing 104 | # swift-bench's test-requirements is probably better than that 105 | command "pip install -e ." 106 | action :run 107 | end 108 | 109 | execute "python-swift-install" do 110 | cwd "#{node['source_root']}/swift" 111 | command "pip install -e .[kmip_keymaster] -r test-requirements.txt" 112 | action :run 113 | end 114 | 115 | # ignore this, apparently ohai doesn't support explicit python3 116 | # https://github.com/chef/ohai/blob/main/lib/ohai/plugins/python.rb#L26 117 | py3_ver_str = shell_out('python3 -c "import sys; print(sys.version)"').stdout 118 | old_py3 = py3_ver_str.split[0].split('.')[1].to_i < 10 119 | 120 | # ubuntu has a patched distutils that does egg-link/editable *installs* to 121 | # /usr/local/lib/../site-packages; but won't look in that path unless 122 | # VIRTUAL_ENV=1 (I mean who installs editable python packages as root!?) 123 | 124 | # N.B. the "correct" answer on ubuntu is actually "dist-packages" 125 | site_packages = shell_out('python3 -c "import site; print(site.getsitepackages()[0])"').stdout 126 | 127 | # N.B. swift-bench has this same problem; but it goes away when the project 128 | # grows a pyproject.toml 129 | # 899958: add pyproject.toml to support pip 23.1 | https://review.opendev.org/c/openstack/swift/+/899958 130 | execute "legacy-python-swift-install" do 131 | cwd "#{node['source_root']}/swift" 132 | command "sudo python3 setup.py develop --script-dir /usr/local/bin --install-dir=#{site_packages}" 133 | action :run 134 | only_if { old_py3 } 135 | end 136 | 137 | execute "install tox" do 138 | command "pip install tox" 139 | action :run 140 | end 141 | 142 | # nvratelimit 143 | 144 | src_dir = "#{node['extra_source']}/swift-nvratelimit" 145 | 146 | execute "nvratelimit-middleware-install" do 147 | cwd src_dir 148 | command "pip install -e ." 149 | action :run 150 | only_if { ::File.directory?(src_dir) } 151 | end 152 | 153 | # add some helpful symlinks 154 | 155 | [ 156 | 'swift', 157 | 'python-swiftclient', 158 | ].each do |dirname| 159 | execute "ln #{dirname}" do 160 | command "ln -s #{node['source_root']}/#{dirname} /home/#{node['username']}/#{dirname}" 161 | creates "/home/#{node['username']}/#{dirname}" 162 | end 163 | end 164 | -------------------------------------------------------------------------------- /cookbooks/swift/recipes/statsd_exporter.rb: -------------------------------------------------------------------------------- 1 | STATSD_EXPORTER_VERSION="0.26.0" 2 | PROMETHEUS_VERSION="2.48.1" 3 | #GRAFANA_VERSION="10.1.1" 4 | ARCH=node.arm? ? "arm64" : "amd64" 5 | 6 | USER_HOME = "/home/#{node['username']}" 7 | 8 | STATSD_EXPORTER_DIRNAME = "statsd_exporter-#{STATSD_EXPORTER_VERSION}.linux-#{ARCH}" 9 | execute "download statsd_exporter" do 10 | cwd USER_HOME 11 | command "curl --fail -OL https://github.com/prometheus/statsd_exporter/releases/download/v#{STATSD_EXPORTER_VERSION}/#{STATSD_EXPORTER_DIRNAME}.tar.gz" 12 | creates "#{STATSD_EXPORTER_DIRNAME}.tar.gz" 13 | action :run 14 | end 15 | execute "unpack statsd_exporter" do 16 | cwd USER_HOME 17 | command "tar xzf #{STATSD_EXPORTER_DIRNAME}.tar.gz" 18 | creates STATSD_EXPORTER_DIRNAME 19 | action :run 20 | end 21 | execute "install statsd_exporter" do 22 | command "cp #{USER_HOME}/#{STATSD_EXPORTER_DIRNAME}/statsd_exporter /usr/local/bin/statsd_exporter" 23 | creates "/usr/local/bin/statsd_exporter" 24 | action :run 25 | end 26 | 27 | PROMETHEUS_DIRNAME = "prometheus-#{PROMETHEUS_VERSION}.linux-#{ARCH}" 28 | execute "download prometheus" do 29 | cwd USER_HOME 30 | command "curl --fail -OL https://github.com/prometheus/prometheus/releases/download/v#{PROMETHEUS_VERSION}/#{PROMETHEUS_DIRNAME}.tar.gz" 31 | creates "#{PROMETHEUS_DIRNAME}.tar.gz" 32 | action :run 33 | end 34 | execute "unpack prometheus" do 35 | cwd USER_HOME 36 | command "tar xzf #{PROMETHEUS_DIRNAME}.tar.gz" 37 | creates PROMETHEUS_DIRNAME 38 | action :run 39 | end 40 | execute "install prometheus" do 41 | command "cp #{USER_HOME}/#{PROMETHEUS_DIRNAME}/prometheus /usr/local/bin/prometheus" 42 | creates "/usr/local/bin/prometheus" 43 | action :run 44 | end 45 | 46 | [ 47 | "prometheus.service", 48 | "statsd_exporter@.service", 49 | ].each do |filename| 50 | cookbook_file "/etc/systemd/system/#{filename}" do 51 | source "etc/systemd/system/#{filename}" 52 | end 53 | end 54 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/pykmip/pykmip.conf.erb: -------------------------------------------------------------------------------- 1 | [client] 2 | host=127.0.0.1 3 | port=5696 4 | certfile=<%= @client_crt %> 5 | keyfile=<%= @client_key %> 6 | ca_certs=<%= @ca_crt %> 7 | username=swift 8 | password=password 9 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/pykmip/server.conf.erb: -------------------------------------------------------------------------------- 1 | [server] 2 | hostname=127.0.0.1 3 | port=5696 4 | certificate_path=<%= @server_crt %> 5 | key_path=<%= @server_key %> 6 | ca_path=<%= @ca_crt %> 7 | auth_suite=TLS1.2 8 | policy_path=/etc/pykmip/policies 9 | database_path=/var/lib/pykmip/pykmip.db 10 | enable_tls_client_auth=False 11 | logging_level=DEBUG 12 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/rc.local.erb: -------------------------------------------------------------------------------- 1 | #!/bin/sh -e 2 | 3 | # 4 | #Copyright (c) 2015-2021, NVIDIA CORPORATION. 5 | #SPDX-License-Identifier: Apache-2.0 6 | 7 | SWIFT_RUN_DIR=/var/run/swift 8 | 9 | if [ ! -d "$SWIFT_RUN_DIR" ]; then 10 | mkdir "$SWIFT_RUN_DIR" 11 | chown <%= @username %>:<%= @username %> "$SWIFT_RUN_DIR" 12 | fi 13 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/rsyncd.conf.erb: -------------------------------------------------------------------------------- 1 | uid = <%= @username %> 2 | gid = <%= @username %> 3 | log file = /var/log/rsyncd.log 4 | pid file = /var/run/rsyncd.pid 5 | address = 0.0.0.0 6 | read only = false 7 | 8 | &include /etc/rsyncd.d 9 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/rsyncd.d/rsync_disk.erb: -------------------------------------------------------------------------------- 1 | [<%= @service %>_<%= @dev %>] 2 | path = /srv/node<%= @n %>/ 3 | lock file = /var/lock/<%= @service %>_<%= @dev %>.lock 4 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/ssl/private/saio.conf.erb: -------------------------------------------------------------------------------- 1 | [req] 2 | default_md = sha256 3 | prompt = no 4 | distinguished_name = subject 5 | x509_extensions = ext 6 | 7 | [subject] 8 | CN = <%= @hostname %> 9 | 10 | [ext] 11 | subjectKeyIdentifier = hash 12 | authorityKeyIdentifier = keyid:always, issuer:always 13 | basicConstraints = CA:true 14 | subjectAltName = @alt-names 15 | keyUsage = digitalSignature, keyEncipherment, keyCertSign 16 | extendedKeyUsage = serverAuth 17 | 18 | [alt-names] 19 | DNS.1 = <%= @hostname %> 20 | DNS.2 = *.<%= @hostname %> 21 | DNS.3 = <%= @ip %>.xip.io 22 | DNS.4 = *.<%= @ip %>.xip.io 23 | IP.1 = <%= @ip %> 24 | 25 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/account-server/replication.conf-template.erb: -------------------------------------------------------------------------------- 1 | [account-replicator] 2 | rsync_module = {replication_ip}::account_{device} 3 | 4 | [account-auditor] 5 | 6 | [account-reaper] 7 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/account-server/server.conf-template.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | disable_fallocate = true 3 | workers = 1 4 | 5 | [pipeline:main] 6 | pipeline = recon account-server 7 | 8 | [app:account-server] 9 | use = egg:swift#account 10 | <% if ! @replication_server -%> 11 | replication_server = false 12 | <% end -%> 13 | 14 | [filter:recon] 15 | use = egg:swift#recon 16 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/account-server/settings.conf.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | bind_port = <%= @bind_port %> 3 | log_name = account-server-<%= @bind_port %> 4 | 5 | <% if @include_replication_settings -%> 6 | [account-replicator] 7 | log_name = account-replicator-<%= @bind_port %> 8 | 9 | [account-auditor] 10 | log_name = account-auditor-<%= @bind_port %> 11 | 12 | [account-reaper] 13 | log_name = account-reaper-<%= @bind_port %> 14 | <% end -%> 15 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/base.conf-template.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | user = <%= @username %> 3 | eventlet_debug = true 4 | log_level = DEBUG 5 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/container-server/replication.conf-template.erb: -------------------------------------------------------------------------------- 1 | [container-replicator] 2 | rsync_module = {replication_ip}::container_{device} 3 | 4 | [container-updater] 5 | 6 | [container-auditor] 7 | 8 | [container-sync] 9 | internal_client_conf_path = /etc/swift/internal-client.conf 10 | 11 | [container-sharder] 12 | auto_shard = <%= @auto_shard %> 13 | shard_container_threshold = 50 14 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/container-server/server.conf-template.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | disable_fallocate = true 3 | workers = 1 4 | 5 | [pipeline:main] 6 | pipeline = recon container-server 7 | 8 | [app:container-server] 9 | use = egg:swift#container 10 | <% if ! @replication_server -%> 11 | replication_server = false 12 | <% end -%> 13 | 14 | [filter:recon] 15 | use = egg:swift#recon 16 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/container-server/settings.conf.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | bind_port = <%= @bind_port %> 3 | log_name = container-server-<%= @bind_port %> 4 | 5 | <% if @include_replication_settings -%> 6 | [container-replicator] 7 | log_name = container-replicator-<%= @bind_port %> 8 | 9 | [container-updater] 10 | log_name = container-updater-<%= @bind_port %> 11 | 12 | [container-auditor] 13 | log_name = container-auditor-<%= @bind_port %> 14 | 15 | [container-sync] 16 | log_name = container-sync-<%= @bind_port %> 17 | 18 | [container-sharder] 19 | log_name = container-sharder-<%= @bind_port %> 20 | <% end -%> 21 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/container-sync-realms.conf.erb: -------------------------------------------------------------------------------- 1 | [test] 2 | key = realm1key 3 | cluster_saio = <%= @base_uri %>/v1/ 4 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/dispersion.conf.erb: -------------------------------------------------------------------------------- 1 | [dispersion] 2 | auth_url = <%= @auth_uri %> 3 | auth_user = test:tester 4 | auth_key = testing 5 | # auth_url = http://saio:5000/v2.0/ 6 | # auth_user = test:tester 7 | # auth_key = testing 8 | # auth_version = 2.0 9 | # endpoint_type = publicURL 10 | # keystone_api_insecure = no 11 | # 12 | # swift_dir = /etc/swift 13 | # dispersion_coverage = 1.0 14 | # retries = 5 15 | # concurrency = 25 16 | # container_populate = yes 17 | # object_populate = yes 18 | # container_report = yes 19 | # object_report = yes 20 | # dump_json = no 21 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/internal-client.conf.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | # swift_dir = /etc/swift 3 | # user = swift 4 | # You can specify default log routing here if you want: 5 | # log_name = swift 6 | # log_facility = LOG_LOCAL0 7 | # log_level = INFO 8 | # log_address = /dev/log 9 | # 10 | # comma separated list of functions to call to setup custom log handlers. 11 | # functions get passed: conf, name, log_to_console, log_route, fmt, logger, 12 | # adapted_logger 13 | # log_custom_handlers = 14 | # 15 | # If set, log_udp_host will override log_address 16 | # log_udp_host = 17 | # log_udp_port = 514 18 | # 19 | # You can enable StatsD logging here: 20 | # log_statsd_host = 21 | # log_statsd_port = 8125 22 | # log_statsd_default_sample_rate = 1.0 23 | # log_statsd_sample_rate_factor = 1.0 24 | # log_statsd_metric_prefix = 25 | 26 | [pipeline:main] 27 | pipeline = catch_errors proxy-logging cache symlink <%= @keymaster_pipeline %> encryption proxy-server 28 | 29 | [app:proxy-server] 30 | use = egg:swift#proxy 31 | account_autocreate = True 32 | allow_open_expired = True 33 | 34 | [filter:symlink] 35 | use = egg:swift#symlink 36 | 37 | [filter:cache] 38 | use = egg:swift#memcache 39 | 40 | [filter:proxy-logging] 41 | use = egg:swift#proxy_logging 42 | 43 | [filter:catch_errors] 44 | use = egg:swift#catch_errors 45 | 46 | [filter:kmip_keymaster] 47 | use = egg:swift#kmip_keymaster 48 | keymaster_config_path = /etc/swift/kmip_keymaster.conf 49 | 50 | [filter:keymaster] 51 | use = egg:swift#keymaster 52 | keymaster_config_path = /etc/swift/keymaster.conf 53 | 54 | [filter:encryption] 55 | use = egg:swift#encryption 56 | disable_encryption = <%= @disable_encryption %> 57 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/kmip_keymaster.conf.erb: -------------------------------------------------------------------------------- 1 | [kmip_keymaster] 2 | active_root_secret_id = 2018 3 | key_id = 1 4 | key_id_2018 = 2 5 | key_id_2019 = 3 6 | host = 127.0.0.1 7 | port = 5696 8 | certfile = <%= @client_crt %> 9 | keyfile = <%= @client_key %> 10 | ca_certs = <%= @ca_crt %> 11 | username = swift 12 | password = ignored 13 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/node.conf-template.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | devices = <%= @srv_path %> 3 | bind_ip = <%= @bind_ip %> 4 | recon_cache_path = <%= @recon_cache_path %> 5 | <% if @statsd_exporter -%> 6 | log_statsd_host = localhost 7 | log_statsd_port = <%= @statsd_port %> 8 | <% end -%> -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/object-server/replication.conf-template.erb: -------------------------------------------------------------------------------- 1 | [object-updater] 2 | 3 | [object-auditor] 4 | 5 | [object-replicator] 6 | sync_method = <%= @sync_method %> 7 | rsync_module = {replication_ip}::object_{device} 8 | 9 | [object-reconstructor] 10 | 11 | [object-relinker] 12 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/object-server/server.conf-template.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | disable_fallocate = true 3 | workers = 1 4 | log_facility = LOG_LOCAL2 5 | # NOTE: servers_per_port necessary for replicator/reconstructor so must go here 6 | servers_per_port = <%= @servers_per_port %> 7 | 8 | [pipeline:main] 9 | pipeline = recon object-server 10 | 11 | [app:object-server] 12 | use = egg:swift#object 13 | <% if ! @replication_server -%> 14 | replication_server = false 15 | <% end -%> 16 | 17 | [filter:recon] 18 | use = egg:swift#recon 19 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/object-server/settings.conf.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | bind_port = <%= @bind_port %> 3 | log_name = object-server-<%= @bind_port %> 4 | 5 | <% if @include_replication_settings -%> 6 | [object-updater] 7 | log_name = object-updater-<%= @bind_port %> 8 | 9 | [object-auditor] 10 | log_name = object-auditor-<%= @bind_port %> 11 | 12 | [object-replicator] 13 | log_name = object-replicator-<%= @bind_port %> 14 | 15 | [object-reconstructor] 16 | log_name = object-reconstructor-<%= @bind_port %> 17 | 18 | [object-relinker] 19 | log_name = object-relinker-<%= @bind_port %> 20 | <% end -%> 21 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/proxy-server/default.conf-template.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | workers = 1 3 | 4 | [filter:catch_errors] 5 | use = egg:swift#catch_errors 6 | 7 | [filter:proxy-logging] 8 | use = egg:swift#proxy_logging 9 | 10 | [filter:subrequest-logging] 11 | use = egg:swift#proxy_logging 12 | access_log_route = subrequest 13 | access_log_statsd_metric_prefix = subrequest 14 | 15 | [filter:healthcheck] 16 | use = egg:swift#healthcheck 17 | 18 | [filter:cache] 19 | use = egg:swift#memcache 20 | 21 | [filter:etag-quoter] 22 | use = egg:swift#etag_quoter 23 | enable_by_default = true 24 | 25 | [filter:bulk] 26 | use = egg:swift#bulk 27 | 28 | [filter:slo] 29 | use = egg:swift#slo 30 | 31 | [filter:dlo] 32 | use = egg:swift#dlo 33 | 34 | [filter:versioned_writes] 35 | use = egg:swift#versioned_writes 36 | allow_versioned_writes = true 37 | allow_object_versioning = true 38 | 39 | [filter:tempurl] 40 | use = egg:swift#tempurl 41 | 42 | [filter:container_sync] 43 | use = egg:swift#container_sync 44 | current = //TEST/SAIO 45 | 46 | [filter:s3api] 47 | use = egg:swift#s3api 48 | s3_acl = False 49 | check_bucket_owner = True 50 | force_swift_request_proxy_log = true 51 | ratelimit_as_client_error = true 52 | 53 | [filter:staticweb] 54 | use = egg:swift#staticweb 55 | 56 | [filter:domain_remap] 57 | use = egg:swift#domain_remap 58 | storage_domain = saio 59 | 60 | [app:proxy-server] 61 | use = egg:swift#proxy 62 | allow_account_management = true 63 | account_autocreate = true 64 | allow_open_expired = true 65 | 66 | [filter:kmip_keymaster] 67 | use = egg:swift#kmip_keymaster 68 | keymaster_config_path = /etc/swift/kmip_keymaster.conf 69 | 70 | [filter:keymaster] 71 | use = egg:swift#keymaster 72 | keymaster_config_path = /etc/swift/keymaster.conf 73 | 74 | [filter:encryption] 75 | use = egg:swift#encryption 76 | disable_encryption = <%= @disable_encryption %> 77 | 78 | [filter:symlink] 79 | use = egg:swift#symlink 80 | 81 | [filter:ratelimit] 82 | use = egg:swift#ratelimit 83 | # max_sleep_time_seconds = 60 84 | # log_sleep_time_seconds = 0 85 | # rate_buffer_seconds = 5 86 | # account_ratelimit = 0 87 | # container_ratelimit_0 = 100 88 | # container_ratelimit_10 = 50 89 | # container_ratelimit_50 = 20 90 | # container_listing_ratelimit_0 = 100 91 | # container_listing_ratelimit_10 = 50 92 | # container_listing_ratelimit_50 = 20 93 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/proxy-server/proxy-noauth.conf.d/20_settings.conf.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | bind_port = 8090 3 | <% if @statsd_exporter -%> 4 | log_statsd_host = localhost 5 | log_statsd_port = 9125 6 | <% end -%> 7 | 8 | [pipeline:main] 9 | pipeline = catch_errors gatekeeper healthcheck proxy-logging cache list-endpoints bulk tempurl slo dlo versioned_writes symlink proxy-logging proxy-server 10 | 11 | [filter:gatekeeper] 12 | use = egg:swift#gatekeeper 13 | shunt_inbound_x_timestamp = false 14 | allow_reserved_names_header = true 15 | 16 | [filter:list-endpoints] 17 | use = egg:swift#list_endpoints 18 | default_response_version = v2 19 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/proxy-server/proxy-server.conf.d/20_settings.conf.erb: -------------------------------------------------------------------------------- 1 | [DEFAULT] 2 | bind_port = 8080 3 | <% if @statsd_exporter -%> 4 | log_statsd_host = localhost 5 | log_statsd_port = 9120 6 | <% end -%> 7 | 8 | [pipeline:main] 9 | pipeline = catch_errors healthcheck proxy-logging domain_remap cache <%= @nvratelimit_pipeline %> etag-quoter container_sync bulk tempurl s3api tempauth ratelimit staticweb slo dlo versioned_writes symlink <%= @keymaster_pipeline %> encryption subrequest-logging proxy-server 10 | 11 | [app:proxy-server] 12 | require_proxy_protocol = <%= @ssl %> 13 | 14 | [filter:tempauth] 15 | use = egg:swift#tempauth 16 | user_admin_admin = admin .admin .reseller_admin 17 | user_test_tester = testing .admin 18 | user_test_tester2 = testing2 .admin 19 | user_test_tester3 = testing3 20 | user_test2_tester2 = testing2 .admin 21 | 22 | [filter:nvratelimit] 23 | use = egg:nvratelimit#nvratelimit 24 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/swift.conf.erb: -------------------------------------------------------------------------------- 1 | [swift-hash] 2 | # random unique strings that can never change (DO NOT LOSE) 3 | swift_hash_path_prefix = changeme 4 | swift_hash_path_suffix = changeme 5 | <% @storage_policies.each_with_index do |name, i| %> 6 | 7 | [storage-policy:<%= i %>] 8 | name = <%= name %> 9 | <% if i == 0 %> 10 | default = yes 11 | <% end %> 12 | <% if name == @ec_policy %> 13 | policy_type = erasure_coding 14 | ec_type = <%= @ec_type %> 15 | ec_num_data_fragments = <%= @ec_replicas - @ec_parity %> 16 | ec_num_parity_fragments = <%= @ec_parity %> 17 | ec_duplication_factor = <%= @ec_duplication %> 18 | <% end %> 19 | <% end %> 20 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/etc/swift/test.conf.erb: -------------------------------------------------------------------------------- 1 | [func_test] 2 | # sample config 3 | auth_uri = <%= @auth_uri %> 4 | 5 | # Primary functional test account (needs admin access to the account) 6 | account = test 7 | username = tester 8 | password = testing 9 | s3_access_key = test:tester 10 | s3_secret_key = testing 11 | 12 | # User on a second account (needs admin access to the account) 13 | account2 = test2 14 | username2 = tester2 15 | password2 = testing2 16 | s3_access_key2 = test:tester2 17 | s3_secret_key2 = testing2 18 | 19 | # User on same account as first, but without admin access 20 | username3 = tester3 21 | password3 = testing3 22 | s3_access_key3 = test:tester3 23 | s3_secret_key3 = testing3 24 | 25 | collate = C 26 | 27 | storage_domain = saio 28 | 29 | [unit_test] 30 | fake_syslog = False 31 | 32 | [probe_test] 33 | # check_server_timeout = 30 34 | validate_rsync = true 35 | proxy_base_url = <%= @base_uri %> 36 | 37 | [s3api_test] 38 | endpoint = <%= @base_uri %> 39 | access_key1 = test:tester 40 | secret_key1 = testing 41 | access_key2 = test:tester2 42 | secret_key2 = testing2 43 | access_key3 = test:tester3 44 | secret_key3 = testing3 45 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/home/aws/config.erb: -------------------------------------------------------------------------------- 1 | [plugins] 2 | endpoint = awscli_plugin_endpoint 3 | 4 | [profile default] 5 | aws_access_key_id = test:tester 6 | aws_secret_access_key = testing 7 | # signature_version can be either s3v4 (for v4 sigs) or s3 (for v2) 8 | s3 = 9 | signature_version = s3v4 10 | endpoint_url = <%= @base_uri %> 11 | s3api = 12 | signature_version = s3v4 13 | endpoint_url = <%= @base_uri %> 14 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/home/aws/credentials.erb: -------------------------------------------------------------------------------- 1 | [default] 2 | aws_access_key_id = test:tester 3 | aws_secret_access_key = testing -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/home/rclone/rclone.erb: -------------------------------------------------------------------------------- 1 | [admin] 2 | type = swift 3 | env_auth = false 4 | user = admin:admin 5 | key = admin 6 | auth = <%= @auth_uri %> 7 | auth_version = 1 8 | 9 | [admin-s3] 10 | type = s3 11 | env_auth = false 12 | access_key_id = admin:admin 13 | secret_access_key = admin 14 | region = us-east-1 15 | endpoint = <%= @base_uri %> 16 | 17 | [test-tester] 18 | type = swift 19 | env_auth = false 20 | user = test:tester 21 | key = testing 22 | auth = <%= @auth_uri %> 23 | auth_version = 1 24 | 25 | [test-tester-s3] 26 | type = s3 27 | env_auth = false 28 | access_key_id = test:tester 29 | secret_access_key = testing 30 | region = us-east-1 31 | endpoint = <%= @base_uri %> 32 | 33 | [test-tester2] 34 | type = swift 35 | env_auth = false 36 | user = test:tester2 37 | key = testing2 38 | auth = <%= @auth_uri %> 39 | auth_version = 1 40 | 41 | [test-tester2-s3] 42 | type = s3 43 | env_auth = false 44 | access_key_id = test:tester2 45 | secret_access_key = testing2 46 | region = us-east-1 47 | endpoint = <%= @base_uri %> 48 | 49 | [test-tester3] 50 | type = swift 51 | env_auth = false 52 | user = test:tester3 53 | key = testing3 54 | auth = <%= @auth_uri %> 55 | auth_version = 1 56 | 57 | [test-tester3-s3] 58 | type = s3 59 | env_auth = false 60 | access_key_id = test:tester3 61 | secret_access_key = testing3 62 | region = us-east-1 63 | endpoint = <%= @base_uri %> 64 | 65 | [test2-tester2] 66 | type = swift 67 | env_auth = false 68 | user = test2:tester2 69 | key = testing2 70 | auth = <%= @auth_uri %> 71 | auth_version = 1 72 | 73 | [test2-tester2-s3] 74 | type = s3 75 | env_auth = false 76 | access_key_id = test2:tester2 77 | secret_access_key = testing2 78 | region = us-east-1 79 | endpoint = <%= @base_uri %> 80 | -------------------------------------------------------------------------------- /cookbooks/swift/templates/default/home/s3cfg.erb: -------------------------------------------------------------------------------- 1 | [default] 2 | access_key = test:tester 3 | secret_key = testing 4 | host_base = <%= @ssl ? "saio" : "saio:8080" %> 5 | host_bucket = <%= @ssl ? "saio" : "saio:8080" %> 6 | use_https = <%= @ssl %> 7 | -------------------------------------------------------------------------------- /localrc-template: -------------------------------------------------------------------------------- 1 | # Any vagrantup box alias *should* work, but who knows 2 | #export VAGRANT_BOX=bento/ubuntu-24.04 3 | # Expect to have to get fancy with non-virtualbox providers; see various README's 4 | #export VAGRANT_DEFAULT_PROVIDER= 5 | export VAGRANT_USERNAME=vagrant # most vagrant boxes should use this 6 | export VAGRANT_HOSTNAME=saio 7 | export VAGRANT_CPUS=1 8 | export VAGRANT_RAM=2048 9 | export FULL_REPROVISION=false 10 | export LOOPBACK_GB=4 # how much storage your swift has 11 | export IP=192.168.8.80 12 | export EXTRA_PACKAGES=ipython3,vim,screen,sysstat 13 | export EXTRA_VMS=0 14 | export PART_POWER=10 15 | export REPLICAS=3 16 | export EC_TYPE=liberasurecode_rs_vand 17 | export EC_REPLICAS=6 18 | export EC_PARITY=2 19 | export EC_DUPLICATION=1 20 | export REGIONS=1 21 | export ZONES=4 22 | export NODES=4 23 | export DISKS=4 # use 2x NODES with SERVERS_PER_PORT > 0 24 | export EC_DISKS=8 25 | export STORAGE_POLICIES=default,ec # list *all* policies here e.g. gold,silver 26 | export EC_POLICY=ec # the policy from STORAGE_POLICIES to make EC e.g. silver 27 | export SERVERS_PER_PORT=0 # 1 port per dev in ring; N obj-servers per port 28 | export REPLICATION_SERVERS=false # or true 29 | export CONTAINER_AUTO_SHARD=true # or false 30 | export OBJECT_SYNC_METHOD=rsync # or ssync 31 | export SSL=false # or true 32 | export ENCRYPTION=false # or true 33 | export KMIP=false # or true 34 | export STATSD_EXPORTER=false # or true 35 | export SWIFT_REPO=https://github.com/openstack/swift 36 | export SWIFT_REPO_BRANCH=master 37 | export SWIFTCLIENT_REPO=https://github.com/openstack/python-swiftclient 38 | export SWIFTBENCH_REPO=https://github.com/openstack/swift-bench 39 | export LIBERASURECODE_REPO=https://github.com/openstack/liberasurecode 40 | export PYECLIB_REPO=https://github.com/openstack/pyeclib 41 | export EXTRA_KEY= # additional pubkey for ~vagrant/.ssh/authorized_keys 42 | export GUI= # non-empty shows VirtualBox console window 43 | export SOURCE_ROOT=/vagrant # clone git repositories at this location 44 | export EXTRA_SOURCE=/vagrant/.scratch 45 | export NVRATELIMIT=false # or true 46 | -------------------------------------------------------------------------------- /tests/test-libvirt.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | source localrc-template 4 | export VAGRANT_DEFAULT_PROVIDER=libvirt 5 | export LIBVIRT_DEFAULT_URI=qemu:///system 6 | export SSL=true 7 | export ENCRYPTION=true 8 | export STATSD_EXPORTER=true 9 | 10 | # TEST JAMMY & NOBLE 11 | for box in 22.04 24.04; do 12 | vagrant destroy -f 13 | VAGRANT_BOX=bento/ubuntu-$box vagrant up 14 | # unittests work 15 | vagrant ssh -c '.unittests' 16 | # functtests only work if you downgarde boto, that's just how swift is right now 17 | vagrant ssh -c 'sudo pip install "boto3<1.36" awscli s3transfer --upgrade' 18 | vagrant ssh -c '.functests' 19 | # you can go as low as 3.7 20 | vagrant ssh -c 'vtox -e py37' 21 | # stock py3 works fine 22 | vagrant ssh -c 'vtox -e py3' 23 | # you can reinstall and swift still works 24 | vagrant ssh -c "reinstallswift && .functests" 25 | # new python is also available 26 | vagrant ssh -c 'vtox -e py313' 27 | done 28 | -------------------------------------------------------------------------------- /tests/test-vbox.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | source localrc-template 4 | export VAGRANT_DEFAULT_PROVIDER=virtualbox 5 | export SSL=true 6 | export ENCRYPTION=true 7 | export STATSD_EXPORTER=true 8 | 9 | # TEST FOCAL 10 | vagrant destroy -f 11 | VAGRANT_BOX=bento/ubuntu-20.04 vagrant up 12 | # unittests work 13 | vagrant ssh -c '.unittests' 14 | # functtests only work if you downgarde boto, that's just how swift is right now 15 | vagrant ssh -c 'sudo pip install "boto3<1.36" awscli s3transfer --upgrade' 16 | vagrant ssh -c '.functests' 17 | # focal has old py36 you can use! 18 | vagrant ssh -c 'vtox -e py36' 19 | # unfortunately stock py3 tox is expected fail 20 | vagrant ssh -c 'vtox -e py3; if [ $? -eq 0 ]; then exit 1 else; exit 0; fi' 21 | # you can work around it tho!? 22 | vagrant ssh -c 'TOX_CONSTRAINTS_FILE=/vagrant/swift/py3-constraints.txt vtox -e py3' 23 | # magic tox constraints make py38 work tho!? 24 | vagrant ssh -c 'vtox -e py38' 25 | # you can reinstall and swift still works 26 | vagrant ssh -c "reinstallswift && .functests" 27 | # focal even has new py3.13!? 28 | vagrant ssh -c 'vtox -e py313' 29 | # TEST JAMMY & NOBLE 30 | for box in 22.04 24.04; do 31 | vagrant destroy -f 32 | VAGRANT_BOX=bento/ubuntu-$box vagrant up 33 | # unittests work 34 | vagrant ssh -c '.unittests' 35 | # functtests only work if you downgarde boto, that's just how swift is right now 36 | vagrant ssh -c 'sudo pip install "boto3<1.36" awscli s3transfer --upgrade' 37 | vagrant ssh -c '.functests' 38 | # you can go as low as 3.7 39 | vagrant ssh -c 'vtox -e py37' 40 | # stock py3 works fine 41 | vagrant ssh -c 'vtox -e py3' 42 | # you can reinstall and swift still works 43 | vagrant ssh -c "reinstallswift && .functests" 44 | # new python is also available 45 | vagrant ssh -c 'vtox -e py313' 46 | done 47 | -------------------------------------------------------------------------------- /tests/test-vmware-linux.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | source localrc-template 4 | export VAGRANT_DEFAULT_PROVIDER=vmware_desktop 5 | export SSL=true 6 | export ENCRYPTION=true 7 | export STATSD_EXPORTER=true 8 | 9 | # When testing with box 10 | # 'bento/ubuntu-22.04' (v202502.21.0) for 'vmware_desktop (amd64)' 11 | # I get an error on bring up 12 | # Warning: Authentication failure. Retrying... 13 | # I assume the box is built wrong and some other 22.04 image might work? 14 | 15 | vagrant destroy -f 16 | VAGRANT_BOX=bento/ubuntu-24.04 vagrant up 17 | # unittests work 18 | vagrant ssh -c '.unittests' 19 | # functtests only work if you downgarde boto, that's just how swift is right now 20 | vagrant ssh -c 'sudo pip install "boto3<1.36" awscli s3transfer --upgrade' 21 | vagrant ssh -c '.functests' 22 | # you can go as low as 3.7 23 | # vagrant ssh -c 'vtox -e py37' 24 | # stock py3 works fine 25 | vagrant ssh -c 'vtox -e py3' 26 | # you can reinstall and swift still works 27 | vagrant ssh -c "reinstallswift && .functests" 28 | # new python is also available 29 | vagrant ssh -c 'vtox -e py313' 30 | -------------------------------------------------------------------------------- /tests/test-vmware.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | source localrc-template 4 | export VAGRANT_DEFAULT_PROVIDER=vmware_desktop 5 | export SSL=true 6 | export ENCRYPTION=true 7 | export STATSD_EXPORTER=true 8 | 9 | # TEST JAMMY & NOBLE 10 | for box in 22.04 24.04; do 11 | vagrant destroy -f 12 | VAGRANT_BOX=bento/ubuntu-$box vagrant up 13 | # unittests work 14 | vagrant ssh -c '.unittests' 15 | # functtests only work if you downgarde boto, that's just how swift is right now 16 | vagrant ssh -c 'sudo pip install "boto3<1.36" awscli s3transfer --upgrade' 17 | vagrant ssh -c '.functests' 18 | # allegedly on arm this fails to install netifaces? 19 | # vagrant ssh -c 'vtox -e py37' 20 | # stock py3 works fine 21 | vagrant ssh -c 'vtox -e py3' 22 | # you can reinstall and swift still works 23 | vagrant ssh -c "reinstallswift && .functests" 24 | # new python is also available 25 | vagrant ssh -c 'vtox -e py313' 26 | done 27 | --------------------------------------------------------------------------------