profitbricks-2.3.1/0000775000175000017500000000000012653761330014756 5ustar ethandethand00000000000000profitbricks-2.3.1/setup.py0000664000175000017500000000511612653761234016476 0ustar ethandethand00000000000000""" Setup script for the ProfitBricks API Python client. """ from __future__ import print_function from setuptools import setup from setuptools.command.test import test as TestCommand import codecs import os import sys import re here = os.path.abspath(os.path.dirname(__file__)) def read(*parts): return codecs.open(os.path.join(here, *parts), 'r').read() def find_version(*file_paths): version_file = read(*file_paths) version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", version_file, re.M) if version_match: return version_match.group(1) raise RuntimeError("Unable to find version string.") if os.path.isfile("README.md"): long_desc = read('README.md') else: long_desc = "ProfitBricks API Client Library for Python" class PyTest(TestCommand): def finalize_options(self): TestCommand.finalize_options(self) self.test_args = ['--strict', '--verbose', '--tb=long', 'tests'] self.test_suite = True def run_tests(self): import pytest errno = pytest.main(self.test_args) sys.exit(errno) setup( name='profitbricks', version=find_version('profitbricks', '__init__.py'), description='ProfitBricks API Client Library for Python', long_description=long_desc, author='Matt Baldwin (stackpointcloud.com)', author_email='baldwin@stackpointcloud.com', url='https://github.com/profitbricks/profitbricks-sdk-python', download_url='https://github.com/profitbricks/profitbricks-sdk-python/tarball/2.3.1', install_requires=['requests>=2.0.0','six>=1.10.0'], packages=['profitbricks'], platforms='any', test_suite='profitbricks.test.test_profitbricks', cmdclass={'test': PyTest}, tests_require=['pytest'], license='Apache 2.0', keywords='profitbricks api client cloud', classifiers=['Development Status :: 5 - Production/Stable', 'Natural Language :: English', 'Environment :: Web Environment', 'Intended Audience :: Developers', 'License :: OSI Approved :: Apache Software License', 'Operating System :: POSIX', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 3', 'Topic :: Software Development :: Libraries :: Python Modules', 'Topic :: Software Development :: Libraries :: Application Frameworks', 'Topic :: Internet :: WWW/HTTP'], extras_require={ 'testing': ['pytest'], } ) profitbricks-2.3.1/setup.cfg0000664000175000017500000000007312653761330016577 0ustar ethandethand00000000000000[egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 profitbricks-2.3.1/LICENSE0000664000175000017500000002606312644000032015753 0ustar ethandethand00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright 2015 ProfitBricks GmbH Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. profitbricks-2.3.1/examples/0000775000175000017500000000000012653761330016574 5ustar ethandethand00000000000000profitbricks-2.3.1/examples/lan_example.py0000664000175000017500000000247612632370277021447 0ustar ethandethand00000000000000"""List LANs """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') lans = client.list_lans(datacenter_id=datacenter_id) print(lans) """Create Complex LAN """ from profitbricks.client import ProfitBricksService, LAN lan_id = '4' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') nics = ['', ''] i = LAN( name='public Lan 4', public=True, nics=nics) response = client.create_lan(datacenter_id=datacenter_id, lan=i) """Create LAN """ from profitbricks.client import ProfitBricksService, LAN lan_id = '4' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') i = LAN( name='public Lan 4', public=True) response = client.create_lan(datacenter_id=datacenter_id, lan=i) """Get LAN Members """ from profitbricks.client import ProfitBricksService lan_id = '4' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') members = client.get_lan_members(datacenter_id=datacenter_id, lan_id=lan_id) profitbricks-2.3.1/examples/volume_example.py0000664000175000017500000000325612632370277022201 0ustar ethandethand00000000000000"""Create volume """ from profitbricks.client import ProfitBricksService, Volume datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') i = Volume( name='Explicitly created volume', size=56, image='', bus='VIRTIO') response = client.create_volume( datacenter_id=datacenter_id, volume=i) """Create snapshot """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' client = ProfitBricksService( username='username', password='password') volume = client.create_snapshot( datacenter_id=datacenter_id, volume_id=volume_id, snapshot_name='', snapshot_description='') """Restore Snapshot """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' snapshot_id = '7df81087-5835-41c6-a10b-3e098593bba4' client = ProfitBricksService( username='username', password='password') response = client.restore_snapshot( datacenter_id=datacenter_id, volume_id=volume_id, snapshot_id=snapshot_id) """Update Volume """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' client = ProfitBricksService( username='username', password='password') volume = client.update_volume( datacenter_id=datacenter_id, volume_id=volume_id, size=100, name='Resized storage to 100 GB') profitbricks-2.3.1/examples/image_examples.py0000664000175000017500000000127312632370277022134 0ustar ethandethand00000000000000"""List Images """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') images = client.list_images() print(images) """Update Image """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') image_id = '7df81087-5835-41c6-a10b-3e098593bbd2' image = client.update_image( image_id, name='New name') """Delete Image """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') image_id = '7df81087-5835-41c6-a10b-3e098593bbd2' image = client.delete_image(image_id) profitbricks-2.3.1/examples/nic_examples.py0000664000175000017500000000330612632370277021622 0ustar ethandethand00000000000000"""List NICs """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') nics = client.list_nics( datacenter_id=datacenter_id, server_id=server_id) for n in nics['items']: print(n['properties']['name']) """Create NIC """ from profitbricks.client import ProfitBricksService, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') i = NIC( name='nic1', ips=['10.2.2.3', '10.2.3.4'], dhcp='true', lan=1, firewall_active=True ) response = client.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) """Create NIC with FirewallRules """ from profitbricks.client import ProfitBricksService, FirewallRule, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' nic_id = '' client = ProfitBricksService( username='username', password='password') fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22, port_range_end=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] i = NIC( name='nic1', ips=['10.2.2.3', '10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) response = client.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) profitbricks-2.3.1/examples/snapshot_examples.py0000664000175000017500000000152012632370277022704 0ustar ethandethand00000000000000"""List Snapshots """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') snapshots = client.list_snapshots() for s in snapshots['items']: print s['properties']['name'] """Get Snapshot """ from profitbricks.client import ProfitBricksService snapshot_id = '7df81087-5835-41c6-a10b-3e098593bba4' # datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') snapshot = client.get_snapshot( snapshot_id=snapshot_id) """Remove Snapshot """ from profitbricks.client import ProfitBricksService snapshot_id = '7df81087-5835-41c6-a10b-3e098593bba4' client = ProfitBricksService( username='username', password='password') snapshot = client.delete_snapshot( snapshot_id=snapshot_id) profitbricks-2.3.1/examples/server_example.py0000664000175000017500000001711512632370277022177 0ustar ethandethand00000000000000"""Create Simple Server """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') i = Server( name='server', ram=4096, cores=4 ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Complex Server """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC, Volume server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' image_id = '226ed8c0-a2fe-11e4-b187-5f1f641608c8' client = ProfitBricksService( username='username', password='password') nic1 = NIC( name='nic1', ips=['10.2.2.5'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.6'], dhcp='true', lan=1, firewall_active=True, ) volume1 = Volume( name='volume6', size=56, image=image_id, bus='VIRTIO' ) volume2 = Volume( name='volume7', size=56, image=image_id, bus='VIRTIO' ) nics = [nic1, nic2] create_volumes = [volume1, volume2] i = Server( name='server11', ram=4096, cores=4, nics=nics, create_volumes=create_volumes ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Server with Existing Volume """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba044' client = ProfitBricksService( username='username', password='password') attach_volumes = [volume_id] i = Server( name='server1', ram=4096, cores=4, attach_volumes=attach_volumes ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Server with New Volumes """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server, Volume server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba044' datacenter_id = 'c4fd1f8a-65e0-42cb-b8fa-ff7e87c3071b' image_id = '27500669-d81b-11e4-aea4-52540066fee9' client = ProfitBricksService( username='username', password='password') volume1 = Volume( name='volume11', size=56, image=image_id, bus='VIRTIO' ) volume2 = Volume( name='volume21', size=56, image=image_id, bus='VIRTIO' ) create_volumes = [volume1, volume2] i = Server( name='server12', ram=4096, cores=4, create_volumes=create_volumes ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Server with NICs Only """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) nics = [nic1, nic2] i = Server( name='server87', ram=4096, cores=4, nics=nics ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Server with Two Existing Volumes """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id1 = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id2 = '800e1cab-99b2-4c30-ba8c-1d273ddba024' client = ProfitBricksService( username='username', password='password') attach_volumes = [volume_id1, volume_id2] i = Server( name='server1', ram=4096, cores=4, attach_volumes=attach_volumes ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Server with Boot Volume """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id1 = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id2 = '800e1cab-99b2-4c30-ba8c-1d273ddba024' boot_volume_id = '800e1cab-99b2-4c30-ba8c-1d273ddba024' client = ProfitBricksService( username='username', password='password') i = Server( name='server14', ram=4096, cores=4, boot_volume_id=boot_volume_id ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Create Server with Existing Volumes and NICs """ from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id1 = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id2 = '800e1cab-99b2-4c30-ba8c-1d273ddba024' boot_volume_id = '800e1cab-99b2-4c30-ba8c-1d273ddba024' client = ProfitBricksService( username='username', password='password') attach_volumes = [volume_id1, volume_id2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) nics = [nic1, nic2] i = Server( name='server1', ram=4096, cores=4, boot_volume_id=boot_volume_id, attach_volumes=attach_volumes, nics=nics ) response = client.create_server( datacenter_id=datacenter_id, server=i) """Start Server """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.start_server( datacenter_id=datacenter_id, server_id=server_id) """Stop Server """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.stop_server( datacenter_id=datacenter_id, server_id=server_id) """Reboot Server """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.reboot_server( datacenter_id=datacenter_id, server_id=server_id) """List Servers """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') servers = client.list_servers(datacenter_id=datacenter_id) """Delete Server """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.delete_server( datacenter_id=datacenter_id, server_id=server_id) """Update Server """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.update_server( datacenter_id=datacenter_id, server_id=server_id, cores=35, ram=2048) profitbricks-2.3.1/examples/datacenter_example.py0000664000175000017500000000560412632370277023003 0ustar ethandethand00000000000000"""List Datacenters """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenters = client.list_datacenters() for d in datacenters['items']: vdc = client.get_datacenter(d['id']) name = vdc['properties']['name'] if name is for d in datacenters['items']: vdc = client.get_datacenter(d['id']) vdc['properties']['name'] if dc_name == vdc['properties']['name']: """Get Datacenter """ from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') datacenter = client.get_datacenter( datacenter_id=datacenter_id) """Create Simple Datacenter """ from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server client = ProfitBricksService( username='username', password='password') i = Datacenter( name='dc1', description='My New Datacenter', location='de/fkb' ) response = client.create_datacenter(datacenter=i) """Create Complex Datacenter """ from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server from profitbricks.client import LAN, NIC, LoadBalancer, FirewallRule, IPBlock, Server image_id = '226ed8c0-a2fe-11e4-b187-5f1f641608c8' client = ProfitBricksService( username='username', password='password') fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22, port_range_end=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nics = [nic1, nic2] volume1 = Volume( name='volume1', size=56, image=image_id, bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image=image_id, bus='VIRTIO' ) volumes = [volume2] server1 = Server( name='My New Server1', ram=4096, cores=4, nics=nics, create_volumes=[volume1] ) servers = [server1] lan1 = LAN( name='public Lan 4', public=True ) lan2 = LAN( name='public Lan 5', public=True ) lans = [lan1, lan2] loadbalancer1 = LoadBalancer( name='LB01', ip='10.2.2.5', dhcp=False) loadbalancers = [loadbalancer1] d = Datacenter( name='My New Datacenter', description='Production environment', location='de/fkb', servers=servers, volumes=volumes, lans=lans, loadbalancers=loadbalancers ) response = client.create_datacenter(datacenter=d) profitbricks-2.3.1/examples/ipblock_examples.py0000664000175000017500000000126412632370277022475 0ustar ethandethand00000000000000"""List IPBlocks """ from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') ipblocks = client.list_ipblocks() print(ipblocks) """Reserve IPBlock """ from profitbricks.client import ProfitBricksService, IPBlock client = ProfitBricksService( username='username', password='password') i = IPBlock(location='de/fra', size=5) ipblock = client.reserve_ipblock(i) """Release IPBlock """ from profitbricks.client import ProfitBricksService ipblock_id = '854467eb-a0d3-4651-ac83-754e2faedba4' client = ProfitBricksService( username='username', password='password') ipblock = client.delete_ipblock(ipblock_id) profitbricks-2.3.1/README.md0000664000175000017500000002712512632367240016243 0ustar ethandethand00000000000000The ProfitBricks Client Library for Python provides you with access to the ProfitBricks REST API. The client library supports both simple and complex requests. It is designed for developers who are building applications in Python. This guide will walk you through getting setup with the library and performing various actions against the API. ## Table of Contents * [Concepts](#concepts) * [Getting Started](#getting-started) * [Installation](#installation) * [Authenticating](#authenticating) * [Using the Module](#using-the-module) * [Additional Documentation and Support](#additional-documentation-and-support) * [How to: Create a Datacenter](#how-to-create-a-datacenter) * [How to: Delete a Datacenter](#how-to-delete-a-datacenter) * [How to: Update Cores, Memory, and Disk](#how-to-update-cores-memory-and-disk) * [How to: List Servers, Volumes, and Data Centers](#how-to-list-servers-volumes-and-data-centers) * [How to: Create Additional Network Interfaces](#how-to-create-additional-network-interfaces) * [Conclusion](#conclusion) ## Concepts The Python Client Library wraps the latest version of the ProfitBricks REST API. All API operations are performed over SSL and authenticated using your ProfitBricks portal credentials. The API can be accessed within an instance running in ProfitBricks or directly over the Internet from any application that can send an HTTPS request and receive an HTTPS response. ## Getting Started Before you begin you will need to have [signed-up](https://www.profitbricks.com/signup) for a ProfitBricks account. The credentials you setup during sign-up will be used to authenticate against the API. ## Installation The Python Client Library is available on [PyPi](https://pypi.python.org/pypi/profitbricks). You can install the latest stable version using pip: pip install profitbricks Done! ## Authenticating Connecting to ProfitBricks is handled by first setting up your authentication. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') You can now use `client` for any future request. ## Using the Module Here are a few examples on how to use the module. In this first one we pull a list of our datacenters. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenters = client.list_datacenters() And in this one we reserve an IPBlock: from profitbricks.client import ProfitBricksService, IPBlock client = ProfitBricksService( username='username', password='password') i = IPBlock(location='de/fra', size=5) ipblock = client.reserve_ipblock(i) Some object creation supports simple and complex requests, such as a server which can be created simply by doing this: from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC, Volume datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') i = Server( name='server1', ram=4096, cores=4 ) response = client.create_server( datacenter_id=datacenter_id, server=i) or if you want one with some volumes and NICs you would do: from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC, Volume server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) nics = [nic1, nic2] create_volumes = [volume1, volume2] i = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=create_volumes ) response = client.create_server( datacenter_id=datacenter_id, server=i) ## Additional Documentation and Support You can find additional examples in our repo [here]. If you find any issues, please let us know via the DevOps Central community or GitHub's issue system and we'll check it out. ## How to: Create a Datacenter ProfitBricks introduces the concept of Virtual Datacenters. These are logically separated from one and the other and allow you to have a self-contained environment for all servers, volumes, networking, snapshots, and so forth. The goal is to give you the same experience as you would have if you were running your own physical datacenter. You will need a datacenter before you can create anything else. Like the server functions, the datacenter functions can be used to create a simple vDC or a complex one. To create a simple one you would do this: from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server client = ProfitBricksService( username='username', password='password') i = Datacenter( username='username', password='password', name='datacenter1', description='My New Datacenter', location='de/fkb' ) response = client.create_datacenter(datacenter=i) To create a complex datacenter you would do this. As you can see, you can create quite a few of the objects you will need later all in one request. These all get serialized in a request queue which you can check using the Requests functions: from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server from profitbricks.client import LAN, NIC, LoadBalancer, FirewallRule client = ProfitBricksService( username='username', password='password') fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nics = [nic1, nic2] volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) volumes = [volume2] server1 = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=[volume1] ) servers = [server1] balancednics = ['', ''] loadbalancer1 = LoadBalancer( name='My LB', balancednics=balancednics) loadbalancers = [loadbalancer1] lan1 = LAN( name='public Lan 4', public=True ) lan2 = LAN( name='public Lan 4', public=True ) lans = [lan1, lan2] d = Datacenter( name='datacenter1', description='my DC', location='de/fkb', servers=servers, volumes=volumes, loadbalancers=loadbalancers, lans=lans ) response = client.create_datacenter(datacenter=d) ## How to: Delete a Datacenter You will want to exercise a bit of caution here. Removing a datacenter will **destroy** all objects contained within that datacenter -- servers, volumes, snapshots, and so on. The objects -- once removed -- will be unrecoverable. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenter_id = '700e1cab-99b2-4c30-ba8c- datacenter = client.delete_datacenter(datacenter_id=datacenter_id) ## How to: Update Cores, Memory, and Disk ProfitBricks allows users to dynamically update cores, memory, and disk independently of each other. This removes the restriction of needing to upgrade to the next size up to receive an increase in memory. You can now simply increase the instances memory keeping your costs in-line with your resource needs. The following code illustrates how you can update cores and memory: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.update_server( datacenter_id=datacenter_id, server_id=server_id, cores=16, ram=2048) This is how you would update your volume's size: from profitbricks.client import ProfitBricksService, Volume datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' client = ProfitBricksService( username='username', password='password') volume = client.update_volume( datacenter_id=datacenter_id, volume_id=volume_id, size=100, name='Resized storage to 100 GB', cpu_hot_unplug=True) ## How to: List Servers, Volumes, and Data Centers Listing resources is fairly straight forward. Grabbing the datacenters: from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenters = client.list_datacenters() Your servers: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') servers = client.list_servers(datacenter_id=datacenter_id) Finally, your volumes: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') volumes = self.volume.list_volumes( datacenter_id=datacenter_id) ## How to: Create Additional Network Interfaces The ProfitBricks platform supports adding multiple NICs to a server. These NICs can be used to create different, segmented networks on the platform. The sample below shows you how to add a second NIC to an existing server: from profitbricks.client import ProfitBricksService, FirewallRule, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') i = NIC( name='nic1', ips=['10.2.2.3','10.2.3.4'], dhcp='true', lan=1, firewall_active=True ) response = client.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) ## Conclusion We touched on only a few ways you can interact with the ProfitBricks API using python. Our repo, located [here], has further examples. If you have any other question, ping us in the community. profitbricks-2.3.1/profitbricks/0000775000175000017500000000000012653761330017457 5ustar ethandethand00000000000000profitbricks-2.3.1/profitbricks/__init__.py0000664000175000017500000000021712653761234021573 0ustar ethandethand00000000000000"""ProfitBricks API Client Library for Python""" __version__ = '2.3.1' API_HOST = 'https://api.profitbricks.com/rest/v2' API__VERSION = '2.0' profitbricks-2.3.1/profitbricks/client.py0000664000175000017500000017733212653761234021327 0ustar ethandethand00000000000000import base64 import json import re import requests from six.moves.urllib.parse import urlencode from profitbricks import ( API_HOST, ) """ProfitBricks Object Classes """ class ProfitBricksService(object): """ ProfitBricksClient Base Class """ def __init__(self, username=None, password=None, host_base=API_HOST, host_cert=None, ssl_verify=True, headers=dict()): self.username = username self.password = password self.host_base = host_base self.host_cert = host_cert self.verify = ssl_verify self.headers = headers """Datacenter Functions """ def get_datacenter(self, datacenter_id, depth=1): """ Retrieves a datacenter by its ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ response = self._perform_request( '/datacenters/%s?depth=%s' % (datacenter_id, str(depth))) return response def list_datacenters(self, depth=1): """ Retrieves a list of all datacenters. """ response = self._perform_request('/datacenters?depth='+str(depth)) return response def delete_datacenter(self, datacenter_id): """ Removes the server from your Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ response = self._perform_request( url='/datacenters/%s' % (datacenter_id), type='DELETE') return response def create_datacenter(self, datacenter): """ Creates a Datacenter -- both simple and complex are supported. """ server_items = [] volume_items = [] lan_items = [] loadbalancer_items = [] entities = dict() properties = { "name": datacenter.name, "location": datacenter.location, } ' Optional Properties' if datacenter.description: properties['description'] = datacenter.description ' Servers ' if len(datacenter.servers) > 0: for server in datacenter.servers: server_items.append(self._create_server_dict(server)) servers = { "items": server_items } server_entities = { "servers": servers } entities.update(server_entities) ' Volumes ' if len(datacenter.volumes) > 0: for volume in datacenter.volumes: volume_items.append(self._create_volume_dict(volume)) volumes = { "items": volume_items } volume_entities = { "volumes": volumes } entities.update(volume_entities) ' Load Balancers ' if len(datacenter.loadbalancers) > 0: for loadbalancer in datacenter.loadbalancers: loadbalancer_items.append( self._create_loadbalancer_dict( loadbalancer ) ) loadbalancers = { "items": loadbalancer_items } loadbalancer_entities = { "loadbalancers": loadbalancers } entities.update(loadbalancer_entities) ' LANs ' if len(datacenter.lans) > 0: for lan in datacenter.lans: lan_items.append( self._create_lan_dict(lan) ) lans = { "items": lan_items } lan_entities = { "lans": lans } entities.update(lan_entities) if len(entities) == 0: raw = { "properties": properties, } else: raw = { "properties": properties, "entities": entities } data = json.dumps(raw) response = self._perform_request( url='/datacenters', type='POST', data=data) return response def update_datacenter(self, datacenter_id, **kwargs): """ Updates a server with the parameters provided. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s' % ( datacenter_id), type='PATCH', data=json.dumps(data)) return response """FirewallRule Functions """ def get_firewall_rule(self, datacenter_id, server_id, nic_id, firewall_rule_id): """ Retrieves a single FirewallRule by ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` :param firewall_rule_id: The unique ID of the FirewallRule. :type firewall_rule_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/nics/%s/firewallrules/%s' % ( datacenter_id, server_id, nic_id, firewall_rule_id)) return response def get_firewall_rules(self, datacenter_id, server_id, nic_id, depth=1): """ Retrieves a list of FirewallRules available in the account. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/nics/%s/firewallrules?depth=%s' % ( datacenter_id, server_id, nic_id, str(depth))) return response def delete_firewall_rule(self, datacenter_id, server_id, nic_id, firewall_rule_id): """ Removes a Firewall rule from the NIC. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` :param firewall_rule_id: The unique ID of the FirewallRule. :type firewall_rule_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/nics/%s/firewallrules/%s' % ( datacenter_id, server_id, nic_id, firewall_rule_id), type='DELETE') return response def create_firewall_rule(self, datacenter_id, server_id, nic_id, firewall_rule): """ Creates a firewall rule on the specified NIC and Server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the Server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` :param firewall_rule: A FirewallRule dict. :type firewall_rule: ``dict`` """ properties = { "name": firewall_rule.name, "protocol": firewall_rule.protocol, } ' Optional Properties' if firewall_rule.source_mac: properties['sourceMac'] = firewall_rule.source_mac if firewall_rule.source_ip: properties['sourceIp'] = firewall_rule.source_ip if firewall_rule.target_ip: properties['targetIp'] = firewall_rule.target_ip if firewall_rule.port_range_start: properties['portRangeStart'] = firewall_rule.port_range_start if firewall_rule.port_range_end: properties['portRangeEnd'] = firewall_rule.port_range_end if firewall_rule.icmp_type: properties['icmpType'] = firewall_rule.icmp_type if firewall_rule.icmp_code: properties['icmpCode'] = firewall_rule.icmp_code data = { "properties": properties } response = self._perform_request( url='/datacenters/%s/servers/%s/nics/%s/firewallrules' % ( datacenter_id, server_id, nic_id), type='POST', data=json.dumps(data)) return response def update_firewall_rule(self, datacenter_id, server_id, nic_id, firewall_rule_id, **kwargs): """ Updates a firewall rule. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` :param firewall_rule_id: The unique ID of the firewall. :type firewall_rule_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] if attr == 'source_mac': data['sourceMac'] = kwargs[attr] elif attr == 'source_ip': data['sourceIp'] = kwargs[attr] elif attr == 'target_ip': data['targetIp'] = kwargs[attr] elif attr == 'port_range_start': data['portRangeStart'] = kwargs[attr] elif attr == 'port_range_end': data['portRangeEnd'] = kwargs[attr] elif attr == 'icmp_type': data['icmpType'] = kwargs[attr] elif attr == 'icmp_code': data['icmpCode'] = kwargs[attr] else: data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s/servers/%s/nics/%s/firewallrules/%s' % ( datacenter_id, server_id, nic_id, firewall_rule_id), type='PATCH', data=json.dumps(data)) return response """Image Functions """ def get_image(self, image_id): """ Retrieves a single image by ID. :param image_id: The unique ID of the image. :type image_id: ``str`` """ response = self._perform_request('/images/%s' % image_id) return response def list_images(self, depth=1): """ Retrieves a list of images available in the datacenter. :param depth: The depth of the response data. :type depth: ``int`` """ response = self._perform_request('/images?depth='+str(depth)) return response def delete_image(self, image_id): """ Removes only user created images. :param image_id: The unique ID of the image. :type image_id: ``str`` """ response = self._perform_request(url='/images/'+image_id, type='DELETE') return response def update_image(self, image_id, **kwargs): """ Replace all properties of an image. """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request(url='/images/'+image_id, type='PATCH', data=json.dumps(data)) return response """IPBlock Functions """ def get_ipblock(self, ipblock_id): """ Retrieves a single IPBlock by ID. :param ipblock_id: The unique ID of the IPBlock. :type ipblock_id: ``str`` """ response = self._perform_request('/ipblocks/%s' % ipblock_id) return response def list_ipblocks(self, depth=1): """ Retrieves a list of IPBlocks available in the account. """ response = self._perform_request('/ipblocks?depth=%s' % str(depth)) return response def delete_ipblock(self, ipblock_id): """ Removes a IPBlock from your account. :param ipblock_id: The unique ID of the IPBlock. :type ipblock_id: ``str`` """ response = self._perform_request( url='/ipblocks/'+ipblock_id, type='DELETE') return response def reserve_ipblock(self, ipblock): """ Reserves an IPBlock within your account. """ properties = { "location": ipblock.location, "size": str(ipblock.size).lower() } raw = { "properties": properties, } data = self._underscore_to_camelcase(json.dumps(raw)) response = self._perform_request( url='/ipblocks', type='POST', data=data) return response """LAN Functions """ def get_lan(self, datacenter_id, lan_id, depth=1): """ Retrieves a single LAN by ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param lan_id: The unique ID of the LAN. :type lan_id: ``str`` """ response = self._perform_request( '/datacenters/%s/lans/%s?depth=%s' % ( datacenter_id, lan_id, str(depth))) return response def list_lans(self, datacenter_id, depth=1): """ Retrieves a list of LANs available in the account. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ response = self._perform_request( '/datacenters/%s/lans?depth=%s' % ( datacenter_id, str(depth))) return response def delete_lan(self, datacenter_id, lan_id): """ Removes a LAN from the Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param lan_id: The unique ID of the LAN. :type lan_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/lans/%s' % ( datacenter_id, lan_id), type='DELETE') return response def create_lan(self, datacenter_id, lan): """ Creates a LAN in the Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param lan: The LAN object to be created. :type lan: ``dict`` """ data = self._underscore_to_camelcase( json.dumps( self._create_lan_dict(lan) ) ) response = self._perform_request( url='/datacenters/%s/lans' % datacenter_id, type='POST', data=data) return response def update_lan(self, datacenter_id, lan_id, **kwargs): """ Updates a LAN :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param lan_id: The unique ID of the LAN. :type lan_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s/lans/%s' % (datacenter_id, lan_id), type='PATCH', data=json.dumps(data)) return response def get_lan_members(self, datacenter_id, lan_id, depth=1): """ Retrieves the list of NICs that are part of the LAN. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param lan_id: The unique ID of the LAN. :type lan_id: ``str`` """ response = self._perform_request( '/datacenters/%s/lans/%s/nics?depth=%s' % ( datacenter_id, lan_id, str(depth))) return response """LoadBalancer Functions """ def get_loadbalancer(self, datacenter_id, loadbalancer_id): """ Retrieves a single LoadBalancer by ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` """ response = self._perform_request( '/datacenters/%s/loadbalancers/%s' % ( datacenter_id, loadbalancer_id)) return response def list_loadbalancers(self, datacenter_id, depth=1): """ Retrieves a list of LoadBalancers in the Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ response = self._perform_request( '/datacenters/%s/loadbalancers?depth=%s' % ( datacenter_id, str(depth))) return response def delete_loadbalancer(self, datacenter_id, loadbalancer_id): """ Removes the LoadBalancer from the Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/loadbalancers/%s' % ( datacenter_id, loadbalancer_id), type='DELETE') return response def create_loadbalancer(self, datacenter_id, loadbalancer): """ Creates a LoadBalancer within the specified DataCenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer: The LoadBalancer object to be created. :type loadbalancer: ``dict`` """ data = self._underscore_to_camelcase( json.dumps( self._create_loadbalancer_dict(loadbalancer) ) ) response = self._perform_request( url='/datacenters/%s/loadbalancers' % datacenter_id, type='POST', data=data) return response def update_loadbalancer(self, datacenter_id, loadbalancer_id, **kwargs): """ Updates a LoadBalancer :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s/loadbalancers/%s' % (datacenter_id, loadbalancer_id), type='PATCH', data=json.dumps(data)) return response def get_loadbalancer_members(self, datacenter_id, loadbalancer_id, depth=1): """ Retrieves the list of NICs that are part of the LAN. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` """ response = self._perform_request( '/datacenters/%s/loadbalancers/%s/balancednics?depth=%s' % ( datacenter_id, loadbalancer_id, str(depth))) return response def add_loadbalanced_nics(self, datacenter_id, loadbalancer_id, nic_id): """ Associates a NIC with the given LoadBalancer. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` :param nic_id: The ID of the NIC. :type nic_id: ``str`` """ data = '{ "id": "' + nic_id + '" }' response = self._perform_request( url='/datacenters/%s/loadbalancers/%s/balancednics' % ( datacenter_id, loadbalancer_id), type='POST', data=data) return response def get_loadbalanced_nic(self, datacenter_id, loadbalancer_id, nic_id, depth=1): """ Gets the properties of a balanced NIC. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` """ response = self._perform_request( '/datacenters/%s/loadbalancers/%s/balancednics/%s?depth=%s' % ( datacenter_id, loadbalancer_id, nic_id, str(depth))) return response def remove_loadbalanced_nic(self, datacenter_id, loadbalancer_id, nic_id): """ Removes a NIC from the loadbalancer. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param loadbalancer_id: The unique ID of the LoadBalancer. :type loadbalancer_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/loadbalancers/%s/balancednics/%s' % ( datacenter_id, loadbalancer_id, nic_id), type='DELETE') return response """Location Functions """ def get_location(self, location_id): """ Retrieves a single Location by ID. :param location_id: The unique ID of the Location. :type location_id: ``str`` """ response = self._perform_request('/locations/'+location_id) return response def list_locations(self): """ Retrieves a list of Location available in the account. """ response = self._perform_request('/locations') return response """NIC Functions """ def get_nic(self, datacenter_id, server_id, nic_id, depth=1): """ Retrieves a NIC by its ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/nics/%s?depth=%s' % ( datacenter_id, server_id, nic_id, str(depth))) return response def list_nics(self, datacenter_id, server_id, depth=1): """ Retrieves a list of all NICs bound to the specified server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/nics?depth=%s' % ( datacenter_id, server_id, str(depth))) return response def delete_nic(self, datacenter_id, server_id, nic_id): """ Removes a NIC from the server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/nics/%s' % ( datacenter_id, server_id, nic_id), type='DELETE') return response def create_nic(self, datacenter_id, server_id, nic): """ Creates a NIC on the specified NIC and Server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the Server. :type server_id: ``str`` :param nic: A NIC dict. :type nic: ``dict`` """ data = json.dumps(self._create_nic_dict(nic)) response = self._perform_request( url='/datacenters/%s/servers/%s/nics' % ( datacenter_id, server_id), type='POST', data=data) return response def update_nic(self, datacenter_id, server_id, nic_id, **kwargs): """ Updates a NIC with the parameters provided. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the Server. :type server_id: ``str`` :param nic_id: The unique ID of the NIC. :type nic_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s/servers/%s/nics/%s' % ( datacenter_id, server_id, nic_id), type='PATCH', data=json.dumps(data)) return response """Request Functions """ def get_request(self, request_id, status=False): """ Retrieves a single request by ID. :param request_id: The unique ID of the request. :type request_id: ``str`` :param status: Retreive the full status of the request. :type status: ``bool`` """ if status: response = self._perform_request( '/requests/'+request_id+'/status') else: response = self._perform_request( '/requests/%s' % request_id) return response def list_requests(self, depth=1): """ Retrieves a list of requests available in the account. """ response = self._perform_request( '/requests?depth=%s' % str(depth)) return response """Server Functions """ def get_server(self, datacenter_id, server_id, depth=1): """ Retrieves a server by its ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s?depth=%s' % ( datacenter_id, server_id, str(depth))) return response def list_servers(self, datacenter_id, depth=1): """ Retrieves a list of all servers bound to the specified server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers?depth=%s' % (datacenter_id, str(depth))) return response def delete_server(self, datacenter_id, server_id): """ Removes the server from your Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s' % ( datacenter_id, server_id), type='DELETE') return response def create_server(self, datacenter_id, server): """ Creates a server within the Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server: A dict of the Server to be created. :type server: ``dict`` """ data = json.dumps(self._create_server_dict(server)) response = self._perform_request( url='/datacenters/%s/servers' % (datacenter_id), type='POST', data=data) return response def update_server(self, datacenter_id, server_id, **kwargs): """ Updates a server with the parameters provided. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ data = {} for attr in kwargs.keys(): if attr == 'boot_volume': boot_volume_properties = { "id": kwargs[attr] } boot_volume_entities = { "bootVolume": boot_volume_properties } data.update(boot_volume_entities) else: data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s/servers/%s' % ( datacenter_id, server_id), type='PATCH', data=json.dumps(data)) return response def get_attached_volumes(self, datacenter_id, server_id, depth=1): """ Retrieves a list of volumes attached to the server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/volumes?depth=%s' % ( datacenter_id, server_id, str(depth))) return response def get_attached_volume(self, datacenter_id, server_id, volume_id): """ Retrieves volume information. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/volumes/%s' % ( datacenter_id, server_id, volume_id)) return response def attach_volume(self, datacenter_id, server_id, volume_id): """ Attaches a volume to a server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ data = '{ "id": "' + volume_id + '" }' response = self._perform_request( url='/datacenters/%s/servers/%s/volumes' % ( datacenter_id, server_id), type='POST', data=data) return response def detach_volume(self, datacenter_id, server_id, volume_id): """ Detaches a volume from a server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/volumes/%s' % ( datacenter_id, server_id, volume_id), type='DELETE') return response def get_attached_cdroms(self, datacenter_id, server_id, depth=1): """ Retrieves a list of CDROMs attached to the server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/cdroms?depth=%s' % ( datacenter_id, server_id, str(depth))) return response def get_attached_cdrom(self, datacenter_id, server_id, cdrom_id): """ Retrieves an attached CDROM. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param cdrom_id: The unique ID of the CDROM. :type cdrom_id: ``str`` """ response = self._perform_request( '/datacenters/%s/servers/%s/cdroms/%s' % ( datacenter_id, server_id, cdrom_id)) return response def attach_cdrom(self, datacenter_id, server_id, cdrom_id): """ Attaches a CDROM to a server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param cdrom_id: The unique ID of the volume. :type cdrom_id: ``str`` """ data = '{ "id": "' + cdrom_id + '" }' response = self._perform_request( url='/datacenters/%s/servers/%s/cdroms' % ( datacenter_id, server_id), type='POST', data=data) return response def detach_cdrom(self, datacenter_id, server_id, cdrom_id): """ Detaches a volume from a server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` :param cdrom_id: The unique ID of the CDROM. :type cdrom_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/cdroms/%s' % ( datacenter_id, server_id, cdrom_id), type='DELETE') return response def start_server(self, datacenter_id, server_id): """ Starts the server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/start' % ( datacenter_id, server_id), type='POST-ACTION') return response def stop_server(self, datacenter_id, server_id): """ Stops the server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/stop' % ( datacenter_id, server_id), type='POST-ACTION') return response def reboot_server(self, datacenter_id, server_id): """ Reboots the server. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param server_id: The unique ID of the server. :type server_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/servers/%s/reboot' % ( datacenter_id, server_id), type='POST-ACTION') return response """Snapshot Functions """ def get_snapshot(self, snapshot_id): """ Retrieves a single snapshot by ID. :param snapshot_id: The unique ID of the snapshot. :type snapshot_id: ``str`` """ response = self._perform_request('/snapshots/%s' % snapshot_id) return response def list_snapshots(self, depth=1): """ Retrieves a list of snapshots available in the account. """ response = self._perform_request( '/snapshots?depth=%s' % str(depth)) return response def delete_snapshot(self, snapshot_id): """ Removes a snapshot from your account. :param snapshot_id: The unique ID of the snapshot. :type snapshot_id: ``str`` """ response = self._perform_request( url='/snapshots/'+snapshot_id, type='DELETE') return response def update_snapshot(self, snapshot_id, **kwargs): """ Removes a snapshot from your account. :param snapshot_id: The unique ID of the snapshot. :type snapshot_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/snapshots/'+snapshot_id, type='PATCH', data=json.dumps(data)) return response def create_snapshot(self, datacenter_id, volume_id, name=None, description=None): """ Creates a snapshot of the specified volume. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ data = {'name': name, 'description': description} response = self._perform_request( '/datacenters/%s/volumes/%s/create-snapshot' % ( datacenter_id, volume_id), type='POST-ACTION-JSON', data=urlencode(data)) return response def restore_snapshot(self, datacenter_id, volume_id, snapshot_id): """ Restores a snapshot to the specified volume. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` :param snapshot_id: The unique ID of the Snapshot. :type snapshot_id: ``str`` """ data = {'snapshotId': snapshot_id} response = self._perform_request( url='/datacenters/%s/volumes/%s/restore-snapshot' % ( datacenter_id, volume_id), type='POST-ACTION', data=urlencode(data)) return response def remove_snapshot(self, snapshot_id): """ Removes a snapshot. :param snapshot_id: The ID of the Snapshot you wish to remove. :type snapshot_id: ``str`` """ response = self._perform_request( url='/snapshots/'+snapshot_id, type='DELETE') return response """Volume Functions """ def get_volume(self, datacenter_id, volume_id): """ Retrieves a single volume by ID. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ response = self._perform_request( '/datacenters/%s/volumes/%s' % (datacenter_id, volume_id)) return response def list_volumes(self, datacenter_id, depth=1): """ Retrieves a list of Volumes in the datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` """ response = self._perform_request( '/datacenters/%s/volumes?depth=%s' % (datacenter_id, str(depth))) return response def delete_volume(self, datacenter_id, volume_id): """ Removes a Volume from the Datacenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ response = self._perform_request( url='/datacenters/%s/volumes/%s' % ( datacenter_id, volume_id), type='DELETE') return response def create_volume(self, datacenter_id, volume): """ Creates a volume within the specified DataCenter. :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param volume: A Volume dict. :type volume: ``dict`` """ data = (json.dumps(self._create_volume_dict(volume))) response = self._perform_request( url='/datacenters/%s/volumes' % datacenter_id, type='POST', data=data) return response def update_volume(self, datacenter_id, volume_id, **kwargs): """ Updates a volume :param datacenter_id: The unique ID of the Datacenter. :type datacenter_id: ``str`` :param volume_id: The unique ID of the volume. :type volume_id: ``str`` """ data = {} for attr in kwargs.keys(): data[self._underscore_to_camelcase(attr)] = kwargs[attr] response = self._perform_request( url='/datacenters/%s/volumes/%s' % ( datacenter_id, volume_id), type='PATCH', data=json.dumps(data)) return response """Private Functions """ def _wrapped_request(self, method, url, params=None, data=None, headers=None, cookies=None, files=None, auth=None, timeout=None, allow_redirects=True, proxies=None, hooks=None, stream=None): headers.update(self.headers) session = requests.Session() return session.request(method, url, params, data, headers, cookies, files, auth, timeout, allow_redirects, proxies, hooks, stream, self.verify, self.host_cert) def _perform_request(self, url, type='GET', data=None, headers=dict()): headers.update({'Authorization': 'Basic %s' % (base64.b64encode( self._b('%s:%s' % (self.username, self.password))).decode('utf-8'))}) url = self._build_url(url) if type == 'POST' or type == 'PUT': headers.update( {'Content-Type': 'application/vnd.profitbricks.resource+json'}) response = self._wrapped_request(type, url, data=data, headers=headers) elif type == 'POST-ACTION-JSON' or type == 'POST-ACTION': headers.update( {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'}) response = self._wrapped_request('POST', url, data=data, headers=headers) if response.status_code == 202 and type == 'POST-ACTION': return True elif response.status_code == 401: raise response.raise_for_status() elif type == 'PATCH': headers.update( {'Content-Type': 'application/vnd.profitbricks.partial-properties+json'}) response = self._wrapped_request(type, url, data=data, headers=headers) else: headers.update( {'Content-Type': 'application/vnd.profitbricks.resource+json'}) response = self._wrapped_request(type, url, params=data, headers=headers) if type == 'DELETE': if response.status_code == 202: return True if not response.ok: err = response.json() code = err['httpStatus'] msg = err['messages'][0]['message'] raise Exception(code, msg) json_response = response.json() if 'location' in response.headers: json_response['requestId'] = self._request_id(response.headers) return json_response def _request_id(self, headers): # The request URL has currently the format: # {host_base}/requests/{request ID}/status # Thus search for a UUID. match = re.search('/requests/([-A-Fa-f0-9]+)/', headers['location']) if match: return match.group(1) else: raise Exception("Failed to extract request ID from response " "header 'location': '{location}'".format( location=headers['location'])) def _build_url(self, uri): url = self.host_base + uri return url def _b(self, s): if isinstance(s, str): return s.encode('utf-8') elif isinstance(s, bytes): return s else: raise TypeError("Invalid argument %r for b()" % (s,)) 'Used to convert python snake case back to mixed case.' def _underscore_to_camelcase(self, value): def camelcase(): yield str.lower while True: yield str.capitalize c = camelcase() return "".join(next(c)(x) if x else '_' for x in value.split("_")) def _create_lan_dict(self, lan): items = [] entities = dict() properties = { "name": lan.name } ' Optional Properties' if lan.public: properties['public'] = str(lan.public).lower() if len(lan.nics) > 0: for nic in lan.nics: nics_properties = { "id": nic } items.append(nics_properties) item_entities = { "items": items } nics_entities = { "nics": item_entities } entities.update(nics_entities) if len(entities) == 0: raw = { "properties": properties, } else: raw = { "properties": properties, "entities": entities } return raw def _create_loadbalancer_dict(self, loadbalancer): items = [] entities = dict() properties = { "name": loadbalancer.name } ' Optional Properties' if loadbalancer.ip: properties['ip'] = loadbalancer.ip if loadbalancer.dhcp: properties['dhcp'] = str(loadbalancer.dhcp).lower() if len(loadbalancer.balancednics) > 0: for nic in loadbalancer.balancednics: balancednic_properties = { "id": nic } items.append(balancednic_properties) item_entities = { "items": items } balancednics_entities = { "balancednics": item_entities } entities.update(balancednics_entities) if len(loadbalancer.balancednics) == 0: raw = { "properties": properties, } else: raw = { "properties": properties, "entities": entities } return raw def _create_nic_dict(self, nic): items = [] properties = { "name": nic.name, "lan": nic.lan, } ' Optional Properties' if nic.ips: properties['ips'] = nic.ips if nic.dhcp: properties['dhcp'] = nic.dhcp if nic.firewall_active: properties['firewallActive'] = nic.firewall_active if len(nic.firewall_rules) > 0: for rule in nic.firewall_rules: items.append(self._create_firewallrules_dict(rule)) rules = { "items": items } entities = { "firewallrules": rules } if len(nic.firewall_rules) == 0: raw = { "properties": properties, } else: raw = { "properties": properties, "entities": entities } return raw def _create_firewallrules_dict(self, rule): properties = {} if rule.name: properties['name'] = rule.name if rule.protocol: properties['protocol'] = rule.protocol if rule.source_mac: properties['sourceMac'] = rule.source_mac if rule.source_ip: properties['sourceIp'] = rule.source_ip if rule.target_ip: properties['targetIp'] = rule.target_ip if rule.port_range_start: properties['portRangeStart'] = rule.port_range_start if rule.port_range_end: properties['portRangeEnd'] = rule.port_range_end if rule.icmp_type: properties['icmpType'] = rule.icmp_type if rule.icmp_code: properties['icmpCode'] = rule.icmp_code raw = { "properties": properties } return raw def _create_server_dict(self, server): volume_items = [] nic_items = [] entities = dict() properties = { "name": server.name, "ram": server.ram, "cores": server.cores } ' Optional Properties' if server.availability_zone: properties['availabilityZone'] = server.availability_zone if server.boot_cdrom: properties['bootCdrom'] = server.boot_cdrom if server.boot_volume_id: boot_volume = { "id": server.boot_volume_id } properties['bootVolume'] = boot_volume if len(server.create_volumes) > 0: for volume in server.create_volumes: volume_items.append(self._create_volume_dict(volume)) volumes = { "items": volume_items } volume_entities = { "volumes": volumes } entities.update(volume_entities) if len(server.nics) > 0: for nic in server.nics: nic_items.append(self._create_nic_dict(nic)) nics = { "items": nic_items } nic_entities = { "nics": nics } entities.update(nic_entities) ' Attach Existing Volume(s) ' if len(server.attach_volumes) > 0: for volume in server.attach_volumes: volume_properties = { "id": volume } volume_items.append(volume_properties) volumes = { "items": volume_items } volume_entities = { "volumes": volumes } entities.update(volume_entities) if len(entities) == 0: raw = { "properties": properties, } else: raw = { "properties": properties, "entities": entities } return raw def _create_volume_dict(self, volume): properties = { "name": volume.name, "size": volume.size } ' Optional Properties' if volume.image: properties['image'] = volume.image if volume.bus: properties['bus'] = volume.bus if volume.disk_type: properties['type'] = volume.disk_type if volume.image is None: properties['licenceType'] = volume.licence_type # if volume.licence_type: # properties['licenceType'] = volume.licence_type if volume.image_password: properties['imagePassword'] = volume.image_password if volume.ssh_keys: properties['sshKeys'] = volume.ssh_keys raw = { "properties": properties } return raw class Datacenter(ProfitBricksService): def __init__(self, name=None, location=None, description=None, volumes=[], servers=[], lans=[], loadbalancers=[], **kwargs): """ Datacenter class initializer. :param name: The Datacenter name.. :type name: ``str`` :param location: The Datacenter geographical location. :type location: ``str`` :param description: Optional description. :type description: ``str`` :param volumes: List of volume dicts. :type volumes: ``list`` :param servers: List of server dicts. :type servers: ``list`` :param lans: List of LAN dicts. :type lans: ``list`` :param loadbalancers: List of loadbalancer dicts. :type loadbalancers: ``list`` """ self.name = name self.description = description self.location = location self.servers = servers self.volumes = volumes self.lans = lans self.loadbalancers = loadbalancers def __repr__(self): return (( ' ...>') % (self.name, self.location, self.description)) class FirewallRule(ProfitBricksService): def __init__(self, name=None, protocol=None, source_mac=None, source_ip=None, target_ip=None, port_range_start=None, port_range_end=None, icmp_type=None, icmp_code=None, **kwargs): """ FirewallRule class initializer. :param name: The name of the FirewallRule. :type name: ``str`` :param protocol: Either TCP or UDP :type protocol: ``str`` :param source_mac: Source MAC you want to restrict. :type source_mac: ``str`` :param source_ip: Source IP you want to restrict. :type source_ip: ``str`` :param target_ip: Target IP you want to restrict. :type target_ip: ``str`` :param port_range_start: Optional port range. :type port_range_start: ``str`` :param port_range_end: Optional port range. :type port_range_end: ``str`` :param icmp_type: Defines the allowed type. :type icmp_type: ``str`` :param icmp_code: Defines the allowed code. :type icmp_code: ``str`` """ self.name = name self.protocol = protocol self.source_mac = source_mac self.source_ip = source_ip self.target_ip = target_ip self.port_range_start = port_range_start self.port_range_end = port_range_end self.icmp_type = icmp_type self.icmp_code = icmp_code def __repr__(self): return (( ' ...>') % (self.name, self.protocol, self.source_mac, self.source_ip, self.target_ip, self.port_range_start, self.port_range_end, self.icmp_type, self.icmp_code)) class IPBlock(ProfitBricksService): def __init__(self, location=None, size=None): """ IPBlock class initializer. :param location: The location for the IP Block. :type location: ``str`` :param size: The number of IPs in the block. :type size: ``str`` """ self.location = location self.size = size def __repr__(self): return (( '') % (self.location, self.size)) class LAN(ProfitBricksService): ''' This is the main class for managing LAN resources. ''' def __init__(self, name=None, public=None, nics=[]): """ LAN class initializer. :param name: Your API username from the portal. :type name: ``str`` :param public: Your API password from the portal. :type public: ``str`` :param nics: A list of NICs :type nics: ``list`` """ self.name = name self.public = public self.nics = nics def __repr__(self): return (( ' ...>') % (self.name, str(self.public))) class LoadBalancer(ProfitBricksService): ''' This is the main class for managing LoadBalancer resources. ''' def __init__(self, name=None, ip=None, dhcp=None, balancednics=[], **kwargs): """ LoadBalancer class initializer. :param name: The name of the LoadBalancer. :type name: ``str`` :param ip: The IP for the loadbalancer. :type ip: ``str`` :param dhcp: Indicates if the LoadBalancer uses DHCP or not. :type dhcp: ``bool`` :param balancednics: A list of NICs associated with the LoadBalancer. :type balancednics: ``list`` """ self.name = name self.ip = ip self.dhcp = dhcp self.balancednics = balancednics def __repr__(self): return (( ' ...>') % (self.name, self.ip, str(self.dhcp))) class NIC(ProfitBricksService): def __init__(self, name=None, ips=None, dhcp=None, lan=None, firewall_active=None, firewall_rules=[], **kwargs): """ NIC class initializer. :param name: The name of the NIC. :type name: ``str`` :param ips: A list of IPs. :type ips: ``list`` :param dhcp: Disable or enable DHCP. Default is enabled. :type dhcp: ``bool`` :param lan: ID of the LAN in which the NIC should reside. :type lan: ``str`` :param firewall_active: Turns the firewall on or not; default is disabled until a rule is added. :type firewall_active: ``bool`` :param firewall_rules: List of Firewall rule dicts. :type firewall_rules: ``list`` """ self.name = name self.ips = ips self.dhcp = dhcp self.lan = lan self.firewall_active = firewall_active self.firewall_rules = firewall_rules def __repr__(self): return (( ' ...>') % (self.name, self.ips, str(self.dhcp), self.lan, str(self.firewall_active))) class Server(ProfitBricksService): ''' This is the main class for managing server resources. ''' def __init__(self, name=None, cores=None, ram=None, availability_zone=None, boot_volume_id=None, boot_cdrom=None, create_volumes=[], attach_volumes=[], nics=[]): """ Server class initializer. :param name: The name of your server.. :type name: ``str`` :param cores: The number of cores for the server. :type cores: ``str`` :param ram: The amount of memory for the server. :type ram: ``str`` :param availability_zone: The availability zone for the server. :type availability_zone: ``str`` :param boot_volume_id: The ID of the boot volume. :type boot_volume_id: ``str`` :param boot_cdrom: Attach a CDROM. :type boot_cdrom: ``str`` :param create_volumes: List of Volume dicts to create. :type create_volumes: ``list`` :param attach_volumes: List of Volume IDs to attach. :type attach_volumes: ``list`` :param nics: List of NIC dicts to create. :type nics: ``list`` """ self.name = name self.cores = cores self.ram = ram self.availability_zone = availability_zone self.boot_volume_id = boot_volume_id self.boot_cdrom = boot_cdrom self.create_volumes = create_volumes self.attach_volumes = attach_volumes self.nics = nics def __repr__(self): return (( ' ...>') % (self.name, self.cores, self.ram, self.availability_zone, self.boot_volume_id, self.boot_cdrom)) class Volume(ProfitBricksService): def __init__(self, name=None, size=None, bus='VIRTIO', image=None, disk_type='HDD', licence_type='UNKNOWN', image_password=None, ssh_keys=[], **kwargs): """ Volume class initializer. :param name: The name of the volume. :type name: ``str`` :param size: The size of the volume. :type size: ``str`` :param bus: The BUS type. Def. VIRTIO. :type bus: ``str`` :param image: The Image ID to use. :type image: ``str`` :param disk_type: The type of storage. Def. HDD :type disk_type: ``str`` :param licence_type: The license type. :type licence_type: ``str`` :param ssh_keys: A list of public SSH keys. :type ssh_keys ``list`` """ self.name = name self.size = size self.image = image self.bus = bus self.disk_type = disk_type self.licence_type = licence_type self.image_password = image_password self.ssh_keys = ssh_keys def __repr__(self): return (( ' ...>') % (self.name, str(self.size), self.image, self.bus, self.disk_type)) profitbricks-2.3.1/tests/0000775000175000017500000000000012653761330016120 5ustar ethandethand00000000000000profitbricks-2.3.1/tests/test_firewall.py0000664000175000017500000000724512632370277021351 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService, FirewallRule server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' nic_id = '' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' firewall_rule_id = '' class TestFirewall(unittest.TestCase): def setUp(self): self.firewall = ProfitBricksService(username='username', password='password') def test_get_all(self): firewalls = self.firewall.get_firewall_rules( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id) self.assertEqual(len(firewalls), 4) self.assertEqual(firewalls['items'][0]['id'], firewall_rule_id) self.assertEqual(firewalls['items'][0]['properties']['name'], 'Open SSH port') self.assertEqual(firewalls['items'][0]['properties']['portRangeStart'], 22) def test_get(self): firewall = self.firewall.get_firewall_rule( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id, firewall_rule_id=firewall_rule_id) self.assertEqual(firewall['id'], firewall_rule_id) self.assertEqual(firewall['properties']['name'], 'Open SSH port') self.assertEqual(firewall['properties']['portRangeStart'], 22) def test_delete(self): firewall = self.firewall.delete_firewall_rule( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id, firewall_rule_id=firewall_rule_id) self.assertTrue(firewall) def test_update(self): firewall = self.firewall.update_firewall_rule( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id, firewall_rule_id=firewall_rule_id, source_mac='01:98:22:22:44:22', target_ip='123.100.101.102') self.assertEqual(firewall['id'], firewall_rule_id) self.assertEqual(firewall['properties']['name'], 'Open SSH port') self.assertEqual(firewall['properties']['portRangeStart'], 22) self.assertEqual( firewall['properties']['sourceMac'], '01:98:22:22:44:22') self.assertEqual( firewall['properties']['targetIp'], '123.100.101.102') def test_create(self): i = FirewallRule( name='Open SSH port', protocol='TCP' ) response = self.firewall.create_firewall_rule( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id, firewall_rule=i) self.assertEqual(response['id'], firewall_rule_id) self.assertEqual(response['properties']['name'], 'Open SSH port') self.assertEqual(response['properties']['portRangeStart'], 22) self.assertEqual(response['properties']['protocol'], 'TCP') self.assertEqual( response['properties']['sourceMac'], '01:23:45:67:89:00') def test_create_optional_value(self): i = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', source_ip='12.2.11.22', port_range_start=22, port_range_end=1000 ) response = self.firewall.create_firewall_rule( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id, firewall_rule=i) self.assertEqual(response['id'], firewall_rule_id) self.assertEqual(response['properties']['name'], 'Open SSH port') self.assertEqual(response['properties']['portRangeStart'], 22) self.assertEqual(response['properties']['protocol'], 'TCP') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_profitbricks.py0000664000175000017500000000000012631417476022225 0ustar ethandethand00000000000000profitbricks-2.3.1/tests/test_location.py0000664000175000017500000000154112632370277021345 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService location_id = 'location_id' class TestLocation(unittest.TestCase): def setUp(self): self.location = ProfitBricksService( username='username', password='password') def test_list_locations(self): locations = self.location.list_locations() self.assertEqual(len(locations), 4) self.assertEqual(locations['items'][0]['id'], 'de/fra') self.assertEqual( locations['items'][0]['properties']['name'], 'Europe / Germany / Frankfurt') def test_get_location(self): location = self.location.get_location(location_id) self.assertEqual(location['id'], 'de/fra') self.assertEqual( location['properties']['name'], 'Europe / Germany / Frankfurt') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_image.py0000664000175000017500000000214512632370277020620 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService class TestImage(unittest.TestCase): def setUp(self): self.image = ProfitBricksService( username='username', password='password') def test_list_images(self): images = self.image.list_images() self.assertEqual(len(images), 4) self.assertEqual( images['items'][0]['id'], '7df81087-5835-41c6-a10b-3e098593bbd2') def test_get_image(self): image_id = '7df81087-5835-41c6-a10b-3e098593bbd2' image = self.image.get_image(image_id) self.assertEqual(image['properties']['name'], 'Ubuntu 14.04') def test_delete_image(self): image_id = '7df81087-5835-41c6-a10b-3e098593bbd2' image = self.image.delete_image(image_id) self.assertTrue(image) def test_update_image(self): image_id = '7df81087-5835-41c6-a10b-3e098593bbd2' image = self.image.update_image( image_id, name='New name') self.assertEqual(image['properties']['name'], 'New name') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_ipblock.py0000664000175000017500000000265312632370277021165 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService, IPBlock ipblock_id = '854467eb-a0d3-4651-ac83-754e2faedba4' class TestIPBlock(unittest.TestCase): def setUp(self): self.ipblock = ProfitBricksService( username='username', password='password') def test_list_ipblocks(self): ipblocks = self.ipblock.list_ipblocks() self.assertEqual(len(ipblocks), 4) self.assertEqual(ipblocks['items'][0]['id'], ipblock_id) self.assertEqual( ipblocks['items'][0]['properties']['size'], 5) self.assertEqual( ipblocks['items'][0]['properties']['location'], 'de/fra') def test_get_ipblock(self): ipblock = self.ipblock.get_ipblock(ipblock_id) self.assertEqual(ipblock['id'], ipblock_id) self.assertEqual(ipblock['properties']['size'], 5) self.assertEqual( ipblock['properties']['location'], 'de/fra') def test_delete_ipblock(self): ipblock = self.ipblock.delete_ipblock(ipblock_id) self.assertTrue(ipblock) def test_reserve_ipblock(self): i = IPBlock(location='de/fra', size=5) ipblock = self.ipblock.reserve_ipblock(i) self.assertEqual(ipblock['id'], ipblock_id) self.assertEqual(ipblock['properties']['size'], 5) self.assertEqual( ipblock['properties']['location'], 'de/fra') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_snapshot.py0000664000175000017500000000454212632370277021400 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService snapshot_id = '7df81087-5835-41c6-a10b-3e098593bba4' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' class TestServer(unittest.TestCase): def setUp(self): self.snapshot = ProfitBricksService( username='username', password='password') def test_list_snapshots(self): snapshots = self.snapshot.list_snapshots() self.assertEqual(len(snapshots), 4) self.assertEqual(snapshots['items'][0]['id'], snapshot_id) self.assertEqual( snapshots['items'][0]['properties']['name'], 'Snapshot of storage X on 12.12.12 12:12:12') self.assertEqual( snapshots['items'][0]['properties']['description'], 'description of a snapshot') self.assertEqual( snapshots['items'][0]['properties']['location'], 'de/fkb') self.assertEqual( snapshots['items'][0]['properties']['size'], 28) def test_get_snapshot(self): snapshot = self.snapshot.get_snapshot( snapshot_id=snapshot_id) self.assertEqual(snapshot['id'], snapshot_id) self.assertEqual( snapshot['properties']['name'], 'Snapshot of storage X on 12.12.12 12:12:12') self.assertEqual( snapshot['properties']['description'], 'description of a snapshot') self.assertEqual( snapshot['properties']['location'], 'de/fkb') self.assertEqual( snapshot['properties']['size'], 28) def test_delete_snapshot(self): snapshot = self.snapshot.delete_snapshot( snapshot_id=snapshot_id) self.assertTrue(snapshot) def test_update_snapshot(self): snapshot = self.snapshot.update_snapshot( snapshot_id='7df81087-5835-41c6-a10b-3e098593bbd2', name='New name') self.assertEqual(snapshot['id'], '7df81087-5835-41c6-a10b-3e098593bbd2') self.assertEqual(snapshot['properties']['name'], 'New name') self.assertEqual( snapshot['properties']['description'], 'description of a snapshot - updated') self.assertEqual( snapshot['properties']['location'], 'de/fkb') self.assertEqual( snapshot['properties']['size'], 28) if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_nic.py0000664000175000017500000000771012632370277020312 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService, FirewallRule, NIC server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' nic_id = '' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' class TestNIC(unittest.TestCase): def setUp(self): self.nic = ProfitBricksService( username='username', password='password') def test_list_nics(self): nics = self.nic.list_nics( datacenter_id=datacenter_id, server_id=server_id) self.assertEqual(len(nics), 4) self.assertEqual(nics['items'][0]['id'], nic_id) self.assertEqual(nics['items'][0]['properties']['name'], 'nic1') self.assertEqual( nics['items'][0]['properties']['mac'], 'AB:21:23:09:78:C2') self.assertEqual(nics['items'][0]['properties']['dhcp'], 'true') self.assertEqual(nics['items'][0]['properties']['lan'], 1) def test_get_nic(self): nic = self.nic.get_nic( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id) self.assertEqual(nic['id'], nic_id) self.assertEqual(nic['properties']['name'], 'nic1') self.assertEqual(nic['properties']['mac'], 'AB:21:23:09:78:C2') self.assertEqual(nic['properties']['dhcp'], 'true') self.assertEqual(nic['properties']['lan'], 1) def test_delete_nic(self): nic = self.nic.delete_nic( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id) self.assertTrue(nic) def test_update_nic(self): nic = self.nic.update_nic( datacenter_id=datacenter_id, server_id=server_id, nic_id=nic_id, ips=['10.2.2.3', '10.2.3.4']) self.assertEqual(nic['id'], nic_id) self.assertEqual(nic['properties']['name'], 'nic1') self.assertEqual(nic['properties']['mac'], 'AB:21:23:09:78:C2') self.assertEqual(nic['properties']['dhcp'], 'true') self.assertEqual(nic['properties']['lan'], 1) def test_create_complex(self): fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] i = NIC( name='nic1', ips=['10.2.2.3', '10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) response = self.nic.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) self.assertEqual(response['id'], nic_id) self.assertEqual(response['properties']['name'], 'nic1') self.assertEqual( response['properties']['mac'], 'AB:21:23:09:78:C2') self.assertEqual(response['properties']['dhcp'], 'true') self.assertEqual(response['properties']['lan'], 1) self.assertListEqual( response['properties']['ips'], ['10.2.2.3']) def test_create_simple(self): i = NIC( name='nic1', ips=['10.2.2.3', '10.2.3.4'], dhcp='true', lan=1, firewall_active=True ) response = self.nic.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) self.assertEqual(response['id'], nic_id) self.assertEqual(response['properties']['name'], 'nic1') self.assertEqual( response['properties']['mac'], 'AB:21:23:09:78:C2') self.assertEqual(response['properties']['dhcp'], 'true') self.assertEqual(response['properties']['lan'], 1) self.assertListEqual( response['properties']['ips'], ['10.2.2.3']) if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_server.py0000664000175000017500000005111112632370277021041 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC, Volume server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' class TestServer(unittest.TestCase): def setUp(self): self.server = ProfitBricksService( username='username', password='password') def test_list_servers(self): servers = self.server.list_servers(datacenter_id=datacenter_id) self.assertEqual(len(servers), 4) self.assertEqual(servers['items'][0]['id'], server_id) self.assertEqual(servers['items'][0]['properties']['name'], 'New Server') self.assertEqual(servers['items'][0]['properties']['cores'], '4') self.assertEqual(servers['items'][0]['properties']['ram'], '4096') self.assertEqual(servers['items'][0]['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(servers['items'][0]['properties']['vmState'], 'SHUTOFF') self.assertEqual(servers['items'][0]['properties']['bootVolume'], None) self.assertEqual(servers['items'][0]['properties']['bootCdrom'], None) def test_get_server(self): server = self.server.get_server( datacenter_id=datacenter_id, server_id=server_id) self.assertEqual(server['id'], server_id) self.assertEqual(server['properties']['name'], 'New Server') self.assertEqual(server['properties']['cores'], '4') self.assertEqual(server['properties']['ram'], '4096') self.assertEqual(server['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(server['properties']['vmState'], 'SHUTOFF') self.assertEqual(server['properties']['bootVolume'], None) self.assertEqual(server['properties']['bootCdrom'], None) def test_delete_server(self): server = self.server.delete_server( datacenter_id=datacenter_id, server_id=server_id) self.assertTrue(server) def test_update_server(self): server = self.server.update_server( datacenter_id=datacenter_id, server_id=server_id, cores=16) self.assertEqual(server['id'], server_id) self.assertEqual(server['properties']['name'], 'server1 - updated') self.assertEqual(server['properties']['cores'], '16') self.assertEqual(server['properties']['ram'], '4096') self.assertEqual(server['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(server['properties']['bootVolume']['id'], '') self.assertEqual(server['properties']['bootCdrom'], None) def test_create_complex(self): nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) nics = [nic1, nic2] create_volumes = [volume1, volume2] i = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=create_volumes ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual( response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_with_existing_volume(self): volume_id = '' attach_volumes = [volume_id] i = Server( name='server1', ram=4096, cores=4, attach_volumes=attach_volumes ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual( response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_with_volumes_only(self): volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) create_volumes = [volume1, volume2] i = Server( name='server1', ram=4096, cores=4, create_volumes=create_volumes ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual(response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_with_nics_only(self): nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) nics = [nic1, nic2] i = Server( name='server1', ram=4096, cores=4, nics=nics ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual(response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_simple(self): i = Server( name='server1', ram=4096, cores=4 ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual(response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_with_two_existing_volumes(self): volume_id1 = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id2 = '800e1cab-99b2-4c30-ba8c-1d273ddba024' attach_volumes = [volume_id1, volume_id2] i = Server( name='server1', ram=4096, cores=4, attach_volumes=attach_volumes ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual(response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_with_boot_volume(self): volume_id1 = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id2 = '800e1cab-99b2-4c30-ba8c-1d273ddba024' boot_volume_id = '800e1cab-99b2-4c30-ba8c-1d273ddba024' attach_volumes = [volume_id1, volume_id2] i = Server( name='server1', ram=4096, cores=4, boot_volume_id=boot_volume_id, attach_volumes=attach_volumes ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual(response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_create_with_nics_and_existing_volume(self): volume_id1 = '700e1cab-99b2-4c30-ba8c-1d273ddba023' volume_id2 = '800e1cab-99b2-4c30-ba8c-1d273ddba024' boot_volume_id = '800e1cab-99b2-4c30-ba8c-1d273ddba024' attach_volumes = [volume_id1, volume_id2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) nics = [nic1, nic2] i = Server( name='server1', ram=4096, cores=4, boot_volume_id=boot_volume_id, attach_volumes=attach_volumes, nics=nics ) response = self.server.create_server( datacenter_id=datacenter_id, server=i) self.assertEqual(response['id'], server_id) self.assertEqual(response['properties']['name'], 'New Server') self.assertEqual(response['properties']['cores'], '4') self.assertEqual(response['properties']['ram'], '4096') self.assertEqual(response['properties']['availabilityZone'], 'ZONE_1') self.assertEqual(response['properties']['vmState'], 'SHUTOFF') def test_get_attached_volumes(self): servers = self.server.get_attached_volumes( datacenter_id=datacenter_id, server_id=server_id) self.assertEqual(len(servers), 4) self.assertEqual(servers['items'][0]['id'], '700e1cab-99b2-4c30-ba8c-1d273ddba025') self.assertEqual(servers['items'][0]['properties']['name'], 'my boot volume for server 1') self.assertEqual(servers['items'][0]['properties']['size'], 80) self.assertEqual(servers['items'][0]['properties']['bus'], 'VIRTIO') self.assertEqual(servers['items'][0]['properties']['image'], None) self.assertEqual(servers['items'][0]['properties']['imagePassword'], None) self.assertEqual(servers['items'][0]['properties']['type'], 'HDD') self.assertEqual(servers['items'][0]['properties']['licenceType'], 'WINDOWS') self.assertFalse(servers['items'][0]['properties']['cpuHotPlug']) self.assertFalse(servers['items'][0]['properties']['cpuHotUnplug']) self.assertFalse(servers['items'][0]['properties']['ramHotPlug']) self.assertFalse(servers['items'][0]['properties']['ramHotUnplug']) self.assertFalse(servers['items'][0]['properties']['nicHotPlug']) self.assertFalse(servers['items'][0]['properties']['nicHotUnplug']) self.assertFalse(servers['items'][0]['properties']['discVirtioHotPlug']) self.assertFalse(servers['items'][0]['properties']['discVirtioHotUnplug']) self.assertFalse(servers['items'][0]['properties']['discScsiHotPlug']) self.assertFalse(servers['items'][0]['properties']['discScsiHotUnplug']) def test_get_attached_volume(self): volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' server = self.server.get_attached_volume( datacenter_id=datacenter_id, server_id=server_id, volume_id=volume_id) self.assertEqual(server['id'], volume_id) self.assertEqual(server['properties']['name'], 'my boot volume for server 1') self.assertEqual(server['properties']['size'], 80) self.assertEqual(server['properties']['bus'], 'VIRTIO') self.assertEqual(server['properties']['image'], None) self.assertEqual(server['properties']['imagePassword'], None) self.assertEqual(server['properties']['type'], 'HDD') self.assertEqual(server['properties']['licenceType'], 'WINDOWS') self.assertFalse(server['properties']['cpuHotPlug']) self.assertFalse(server['properties']['cpuHotUnplug']) self.assertFalse(server['properties']['ramHotPlug']) self.assertFalse(server['properties']['ramHotUnplug']) self.assertFalse(server['properties']['nicHotPlug']) self.assertFalse(server['properties']['nicHotUnplug']) self.assertFalse(server['properties']['discVirtioHotPlug']) self.assertFalse(server['properties']['discVirtioHotUnplug']) self.assertFalse(server['properties']['discScsiHotPlug']) self.assertFalse(server['properties']['discScsiHotUnplug']) def test_detach_volume(self): volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' server = self.server.detach_volume( datacenter_id=datacenter_id, server_id=server_id, volume_id=volume_id) self.assertTrue(server) def test_attach_volume(self): volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' server = self.server.attach_volume( datacenter_id=datacenter_id, server_id=server_id, volume_id=volume_id) self.assertEqual(server['id'], volume_id) self.assertEqual(server['properties']['name'], 'my boot volume for server 1') self.assertEqual(server['properties']['size'], 80) self.assertEqual(server['properties']['bus'], 'VIRTIO') self.assertEqual(server['properties']['image'], None) self.assertEqual(server['properties']['imagePassword'], None) self.assertEqual(server['properties']['type'], 'HDD') self.assertEqual(server['properties']['licenceType'], 'WINDOWS') self.assertFalse(server['properties']['cpuHotPlug']) self.assertFalse(server['properties']['cpuHotUnplug']) self.assertFalse(server['properties']['ramHotPlug']) self.assertFalse(server['properties']['ramHotUnplug']) self.assertFalse(server['properties']['nicHotPlug']) self.assertFalse(server['properties']['nicHotUnplug']) self.assertFalse(server['properties']['discVirtioHotPlug']) self.assertFalse(server['properties']['discVirtioHotUnplug']) self.assertFalse(server['properties']['discScsiHotPlug']) self.assertFalse(server['properties']['discScsiHotUnplug']) def test_get_attached_cdroms(self): servers = self.server.get_attached_cdroms( datacenter_id=datacenter_id, server_id=server_id) self.assertEqual(len(servers), 4) self.assertEqual(servers['items'][0]['id'], '7df81087-5835-41c6-a10b-3e098593bbd2') self.assertEqual(servers['items'][0]['properties']['name'], 'Ubuntu 14.04') self.assertEqual(servers['items'][0]['properties']['size'], 28) self.assertEqual(servers['items'][0]['properties']['description'], 'Ubuntu image description') self.assertEqual(servers['items'][0]['properties']['location'], 'de/fkb') self.assertEqual(servers['items'][0]['properties']['imageType'], 'CDROM') self.assertEqual(servers['items'][0]['properties']['licenceType'], 'UNKNOWN') self.assertFalse(servers['items'][0]['properties']['public']) self.assertFalse(servers['items'][0]['properties']['cpuHotPlug']) self.assertFalse(servers['items'][0]['properties']['cpuHotUnplug']) self.assertFalse(servers['items'][0]['properties']['ramHotPlug']) self.assertFalse(servers['items'][0]['properties']['ramHotUnplug']) self.assertFalse(servers['items'][0]['properties']['nicHotPlug']) self.assertFalse(servers['items'][0]['properties']['nicHotUnplug']) self.assertFalse(servers['items'][0]['properties']['discVirtioHotPlug']) self.assertFalse(servers['items'][0]['properties']['discVirtioHotUnplug']) self.assertFalse(servers['items'][0]['properties']['discScsiHotPlug']) self.assertFalse(servers['items'][0]['properties']['discScsiHotUnplug']) def test_get_attached_cdrom(self): cdrom_id = '7df81087-5835-41c6-a10b-3e098593bbd2' server = self.server.get_attached_cdrom( datacenter_id=datacenter_id, server_id=server_id, cdrom_id=cdrom_id) self.assertEqual(server['id'], cdrom_id) self.assertEqual(server['properties']['name'], 'Ubuntu 14.04') self.assertEqual(server['properties']['size'], 28) self.assertEqual(server['properties']['description'], 'Ubuntu image description') self.assertEqual(server['properties']['location'], 'de/fkb') self.assertEqual(server['properties']['imageType'], 'CDROM') self.assertEqual(server['properties']['licenceType'], 'UNKNOWN') self.assertFalse(server['properties']['public']) self.assertFalse(server['properties']['cpuHotPlug']) self.assertFalse(server['properties']['cpuHotUnplug']) self.assertFalse(server['properties']['ramHotPlug']) self.assertFalse(server['properties']['ramHotUnplug']) self.assertFalse(server['properties']['nicHotPlug']) self.assertFalse(server['properties']['nicHotUnplug']) self.assertFalse(server['properties']['discVirtioHotPlug']) self.assertFalse(server['properties']['discVirtioHotUnplug']) self.assertFalse(server['properties']['discScsiHotPlug']) self.assertFalse(server['properties']['discScsiHotUnplug']) def test_detach_cdrom(self): cdrom_id = '7df81087-5835-41c6-a10b-3e098593bbd2' server = self.server.detach_cdrom( datacenter_id=datacenter_id, server_id=server_id, cdrom_id=cdrom_id) self.assertTrue(server) def test_attach_cdrom(self): cdrom_id = '7df81087-5835-41c6-a10b-3e098593bbd2' server = self.server.attach_cdrom( datacenter_id=datacenter_id, server_id=server_id, cdrom_id=cdrom_id) self.assertEqual(server['id'], cdrom_id) self.assertEqual(server['properties']['name'], 'Ubuntu 14.04') self.assertEqual(server['properties']['size'], 28) self.assertEqual(server['properties']['description'], 'Ubuntu image description') self.assertEqual(server['properties']['location'], 'de/fkb') self.assertEqual(server['properties']['imageType'], 'CDROM') self.assertEqual(server['properties']['licenceType'], 'UNKNOWN') self.assertFalse(server['properties']['public']) self.assertFalse(server['properties']['cpuHotPlug']) self.assertFalse(server['properties']['cpuHotUnplug']) self.assertFalse(server['properties']['ramHotPlug']) self.assertFalse(server['properties']['ramHotUnplug']) self.assertFalse(server['properties']['nicHotPlug']) self.assertFalse(server['properties']['nicHotUnplug']) self.assertFalse(server['properties']['discVirtioHotPlug']) self.assertFalse(server['properties']['discVirtioHotUnplug']) self.assertFalse(server['properties']['discScsiHotPlug']) self.assertFalse(server['properties']['discScsiHotUnplug']) def test_start_server(self): server = self.server.start_server( datacenter_id=datacenter_id, server_id=server_id) self.assertTrue(server) def test_stop_server(self): server = self.server.stop_server( datacenter_id=datacenter_id, server_id=server_id) self.assertTrue(server) def test_reboot_server(self): server = self.server.reboot_server( datacenter_id=datacenter_id, server_id=server_id) self.assertTrue(server) if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_provisioning_requests.py0000664000175000017500000000213012632370277024211 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService class TestProvisioningRequest(unittest.TestCase): def setUp(self): self.provisioning_request = ProfitBricksService( username='username', password='password') def test_list_requests(self): prov_requests = self.provisioning_request.list_requests() self.assertEqual(len(prov_requests), 4) self.assertEqual( prov_requests['items'][0]['id'], '59359eae-cdcd-406f-900b-58b3ad9d8de9') def test_get_request(self): request_id = '59359eae-cdcd-406f-900b-58b3ad9d8de9' prov_request = self.provisioning_request.get_request(request_id) self.assertEqual(prov_request['metadata']['createdBy'], 'User X') def test_get_request_with_status(self): request_id = '59359eae-cdcd-406f-900b-58b3ad9d8de9' prov_request = self.provisioning_request.get_request( request_id, status=True) self.assertEqual( prov_request['metadata']['requestStatus'], 'RUNNING') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_lan.py0000664000175000017500000000466112632370277020315 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService, LAN lan_id = '4' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' class TestLan(unittest.TestCase): def setUp(self): self.lan = ProfitBricksService(username='username', password='password') def test_list_lans(self): lans = self.lan.list_lans(datacenter_id=datacenter_id) self.assertEqual(len(lans), 4) self.assertEqual(lans['items'][0]['id'], lan_id) self.assertEqual(lans['items'][0]['properties']['name'], 'public Lan 4') def test_get_lan(self): lan = self.lan.get_lan(datacenter_id=datacenter_id, lan_id=lan_id) self.assertEqual(lan['properties']['name'], 'public Lan 4') self.assertTrue(lan['properties']['public']) def test_delete_lan(self): lan = self.lan.delete_lan(datacenter_id=datacenter_id, lan_id=lan_id) self.assertTrue(lan) def test_update_lan(self): lan = self.lan.update_lan(datacenter_id=datacenter_id, lan_id=lan_id, name='new lan 4 name', public=False) self.assertEqual(lan['properties']['name'], 'public Lan 4') self.assertTrue(lan['properties']['public']) def test_create_lan(self): i = LAN( name='public Lan 4', public=True) response = self.lan.create_lan(datacenter_id=datacenter_id, lan=i) self.assertEqual(response['properties']['name'], 'public Lan 4') self.assertTrue(response['properties']['public']) def test_create_complex_lan(self): nics = ['', ''] i = LAN( name='public Lan 4', public=True, nics=nics) response = self.lan.create_lan(datacenter_id=datacenter_id, lan=i) self.assertEqual(response['properties']['name'], 'public Lan 4') self.assertTrue(response['properties']['public']) def test_get_lan_members(self): members = self.lan.get_lan_members(datacenter_id=datacenter_id, lan_id=lan_id) self.assertEqual(len(members), 4) self.assertEqual(members['items'][0]['id'], '') self.assertEqual(members['items'][0]['properties']['name'], 'nic1') self.assertEqual(members['items'][0]['properties']['mac'], 'AB:21:23:09:78:C2') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_volume.py0000664000175000017500000001763412632370277021056 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService, Volume volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' snapshot_id = '7df81087-5835-41c6-a10b-3e098593bba4' class TestVolume(unittest.TestCase): def setUp(self): self.volume = ProfitBricksService( username='username', password='password') def test_list_volumes(self): volumes = self.volume.list_volumes( datacenter_id=datacenter_id) self.assertEqual(len(volumes), 4) self.assertEqual(volumes['items'][0]['id'], volume_id) self.assertEqual(volumes['items'][0]['properties']['name'], 'my boot volume for server 1') self.assertEqual(volumes['items'][0]['properties']['size'], 80) self.assertEqual(volumes['items'][0]['properties']['licenceType'], 'WINDOWS') self.assertFalse(volumes['items'][0]['properties']['cpuHotPlug']) self.assertFalse(volumes['items'][0]['properties']['cpuHotUnplug']) self.assertFalse(volumes['items'][0]['properties']['ramHotPlug']) self.assertFalse(volumes['items'][0]['properties']['ramHotUnplug']) self.assertFalse(volumes['items'][0]['properties']['nicHotPlug']) self.assertFalse(volumes['items'][0]['properties']['nicHotUnplug']) self.assertFalse(volumes['items'][0]['properties']['discVirtioHotPlug']) self.assertFalse(volumes['items'][0]['properties']['discVirtioHotUnplug']) self.assertFalse(volumes['items'][0]['properties']['discScsiHotPlug']) self.assertFalse(volumes['items'][0]['properties']['discScsiHotUnplug']) self.assertEqual(volumes['items'][0]['properties']['bus'], 'VIRTIO') self.assertEqual(volumes['items'][0]['properties']['type'], 'HDD') def test_get_volume(self): volume = self.volume.get_volume( datacenter_id=datacenter_id, volume_id=volume_id) self.assertEqual(volume['properties']['name'], 'my boot volume for server 1') self.assertEqual(volume['properties']['size'], 80) self.assertEqual(volume['properties']['licenceType'], 'WINDOWS') self.assertFalse(volume['properties']['cpuHotPlug']) self.assertFalse(volume['properties']['cpuHotUnplug']) self.assertFalse(volume['properties']['ramHotPlug']) self.assertFalse(volume['properties']['ramHotUnplug']) self.assertFalse(volume['properties']['nicHotPlug']) self.assertFalse(volume['properties']['nicHotUnplug']) self.assertFalse(volume['properties']['discVirtioHotPlug']) self.assertFalse(volume['properties']['discVirtioHotUnplug']) self.assertFalse(volume['properties']['discScsiHotPlug']) self.assertFalse(volume['properties']['discScsiHotUnplug']) self.assertEqual(volume['properties']['bus'], 'VIRTIO') self.assertEqual(volume['properties']['type'], 'HDD') def test_delete_volume(self): volume = self.volume.delete_volume( datacenter_id=datacenter_id, volume_id=volume_id) self.assertTrue(volume) def test_update_volume(self): volume = self.volume.update_volume( datacenter_id=datacenter_id, volume_id=volume_id, size=100, name='Resized storage to 100 GB', cpu_hot_unplug=True) self.assertEqual( volume['properties']['name'], 'Resized storage to 100 GB') self.assertEqual(volume['properties']['size'], 100) def test_create_volume(self): i = Volume( name='Explicitly created volume', size=56, image='', bus='VIRTIO') response = self.volume.create_volume( datacenter_id=datacenter_id, volume=i) self.assertEqual( response['properties']['name'], 'my boot volume for server 1') self.assertEqual(response['properties']['size'], 80) self.assertEqual(response['properties']['licenceType'], 'WINDOWS') self.assertFalse(response['properties']['cpuHotPlug']) self.assertFalse(response['properties']['cpuHotUnplug']) self.assertFalse(response['properties']['ramHotPlug']) self.assertFalse(response['properties']['ramHotUnplug']) self.assertFalse(response['properties']['nicHotPlug']) self.assertFalse(response['properties']['nicHotUnplug']) self.assertFalse(response['properties']['discVirtioHotPlug']) self.assertFalse(response['properties']['discVirtioHotUnplug']) self.assertFalse(response['properties']['discScsiHotPlug']) self.assertFalse(response['properties']['discScsiHotUnplug']) self.assertEqual(response['properties']['bus'], 'VIRTIO') self.assertEqual(response['properties']['type'], 'HDD') def test_create_optional_value(self): i = Volume( name='Explicitly created volume', size=56, image='', bus='VIRTIO', ram_hot_plug=True, cpu_hot_unplug=True) response = self.volume.create_volume( datacenter_id=datacenter_id, volume=i) self.assertEqual( response['properties']['name'], 'my boot volume for server 1') self.assertEqual(response['properties']['size'], 80) self.assertEqual(response['properties']['licenceType'], 'WINDOWS') self.assertFalse(response['properties']['cpuHotPlug']) self.assertFalse(response['properties']['cpuHotUnplug']) self.assertFalse(response['properties']['ramHotPlug']) self.assertFalse(response['properties']['ramHotUnplug']) self.assertFalse(response['properties']['nicHotPlug']) self.assertFalse(response['properties']['nicHotUnplug']) self.assertFalse(response['properties']['discVirtioHotPlug']) self.assertFalse(response['properties']['discVirtioHotUnplug']) self.assertFalse(response['properties']['discScsiHotPlug']) self.assertFalse(response['properties']['discScsiHotUnplug']) self.assertEqual(response['properties']['bus'], 'VIRTIO') self.assertEqual(response['properties']['type'], 'HDD') def test_create_snapshot(self): volume = self.volume.create_snapshot( datacenter_id=datacenter_id, volume_id=volume_id, name='', description='') self.assertEqual(volume['id'], snapshot_id) self.assertEqual( volume['properties']['name'], 'Snapshot of storage X on 12.12.12 12:12:12 - updated') self.assertEqual(volume['properties']['description'], 'description of a snapshot - updated') self.assertEqual(volume['properties']['location'], 'de/fkb') self.assertEqual(volume['properties']['size'], 28) self.assertEqual(volume['properties']['licenceType'], 'WINDOWS') self.assertFalse(volume['properties']['cpuHotPlug']) self.assertFalse(volume['properties']['cpuHotUnplug']) self.assertFalse(volume['properties']['ramHotPlug']) self.assertFalse(volume['properties']['ramHotUnplug']) self.assertFalse(volume['properties']['nicHotPlug']) self.assertFalse(volume['properties']['nicHotUnplug']) self.assertFalse(volume['properties']['discVirtioHotPlug']) self.assertFalse(volume['properties']['discVirtioHotUnplug']) self.assertFalse(volume['properties']['discScsiHotPlug']) self.assertFalse(volume['properties']['discScsiHotUnplug']) def test_restore_snapshot(self): response = self.volume.restore_snapshot( datacenter_id=datacenter_id, volume_id=volume_id, snapshot_id=snapshot_id) self.assertTrue(response) def test_remove_snapshot(self): volume = self.volume.remove_snapshot(snapshot_id=snapshot_id) self.assertTrue(volume) if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_datacenter.py0000664000175000017500000001253112647430265021650 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server from profitbricks.client import LAN, NIC, LoadBalancer, FirewallRule datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' class TestDatacenter(unittest.TestCase): def setUp(self): self.datacenter = ProfitBricksService( username='username', password='password') def test_get_all(self): datacenters = self.datacenter.list_datacenters() self.assertEqual(len(datacenters), 4) self.assertEqual(datacenters['items'][0]['id'], datacenter_id) # self.assertEqual( # datacenters['items'][0]['properties']['name'], 'datacenter1') # self.assertEqual( # datacenters['items'][0]['properties']['description'], 'Description of my DC') # self.assertEqual( # datacenters['items'][0]['properties']['location'], 'de/fkb') # self.assertEqual( # datacenters['items'][0]['properties']['version'], 4) def test_get(self): datacenter = self.datacenter.get_datacenter( datacenter_id=datacenter_id) self.assertEqual(datacenter['id'], datacenter_id) self.assertEqual(datacenter['properties']['name'], 'datacenter1') self.assertEqual(datacenter['properties']['description'], 'Description of my DC') self.assertEqual(datacenter['properties']['version'], 4) self.assertEqual(datacenter['properties']['location'], 'de/fkb') def test_delete(self): datacenter = self.datacenter.delete_datacenter( datacenter_id=datacenter_id) self.assertTrue(datacenter) def test_update(self): datacenter = self.datacenter.update_datacenter( datacenter_id=datacenter_id, name='Partially updated datacenter name') self.assertEqual(datacenter['id'], datacenter_id) self.assertEqual(datacenter['properties']['name'], 'datacenter1') self.assertEqual(datacenter['properties']['description'], 'Description of my DC') self.assertEqual(datacenter['properties']['version'], 4) self.assertEqual(datacenter['properties']['location'], 'de/fkb') def test_create_simple(self): i = Datacenter( name='datacenter1', description='My New Datacenter', location='de/fkb' ) response = self.datacenter.create_datacenter(datacenter=i) self.assertEqual(response['id'], datacenter_id) self.assertEqual(response['properties']['name'], 'datacenter1') self.assertEqual(response['properties']['description'], 'My New Datacenter') self.assertEqual(response['properties']['version'], 4) self.assertEqual(response['properties']['location'], 'de/fkb') def test_create_complex(self): """ Creates a complex Datacenter in a single request. """ fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nics = [nic1, nic2] volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) volumes = [volume2] server1 = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=[volume1] ) servers = [server1] balancednics = ['', ''] loadbalancer1 = LoadBalancer( name='My LB', balancednics=balancednics) loadbalancers = [loadbalancer1] lan1 = LAN( name='public Lan 4', public=True ) lan2 = LAN( name='public Lan 4', public=True ) lans = [lan1, lan2] d = Datacenter( name='datacenter1', description='my DC', location='de/fkb', servers=servers, volumes=volumes, loadbalancers=loadbalancers, lans=lans ) response = self.datacenter.create_datacenter(datacenter=d) print(response) self.assertEqual(response['id'], datacenter_id) self.assertEqual(response['properties']['name'], 'My New Datacenter') self.assertEqual(response['properties']['description'], 'Production environment') self.assertEqual(response['properties']['version'], 4) self.assertEqual(response['properties']['location'], 'de/fkb') if __name__ == '__main__': unittest.main() profitbricks-2.3.1/tests/test_loadbalancer.py0000664000175000017500000001112312632370277022141 0ustar ethandethand00000000000000import unittest from profitbricks.client import ProfitBricksService, LoadBalancer loadbalancer_id = '' nic_id = '' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' class TestLoadBalancer(unittest.TestCase): def setUp(self): self.loadbalancer = ProfitBricksService(username='username', password='password') def test_get_all(self): loadbalancers = self.loadbalancer.list_loadbalancers( datacenter_id=datacenter_id) self.assertEqual(len(loadbalancers), 4) self.assertEqual(loadbalancers['items'][0]['id'], loadbalancer_id) self.assertEqual(loadbalancers['items'][0]['properties']['name'], 'My LB') def test_get_loadbalancer(self): loadbalancer = self.loadbalancer.get_loadbalancer( datacenter_id=datacenter_id, loadbalancer_id=loadbalancer_id) self.assertEqual(loadbalancer['properties']['name'], 'My LB') self.assertEqual(loadbalancer['properties']['ip'], '10.2.2.3') self.assertTrue(loadbalancer['properties']['dhcp']) def test_delete_loadbalancer(self): loadbalancer = self.loadbalancer.delete_loadbalancer( datacenter_id=datacenter_id, loadbalancer_id=loadbalancer_id) self.assertTrue(loadbalancer) def test_update_loadbalancer(self): loadbalancer = self.loadbalancer.update_loadbalancer( datacenter_id=datacenter_id, loadbalancer_id=loadbalancer_id, ip='10.2.2.4') self.assertEqual(loadbalancer['properties']['name'], 'My LB') self.assertEqual(loadbalancer['properties']['ip'], '10.2.2.4') self.assertTrue(loadbalancer['properties']['dhcp']) def test_create_loadbalancer(self): i = LoadBalancer( name='My LB') response = self.loadbalancer.create_loadbalancer( datacenter_id=datacenter_id, loadbalancer=i) self.assertEqual(response['properties']['name'], 'My LB') self.assertEqual(response['properties']['ip'], '10.2.2.3') self.assertTrue(response['properties']['dhcp']) def test_create_with_balancednics(self): balancednics = ['', ''] i = LoadBalancer( name='My LB', balancednics=balancednics) response = self.loadbalancer.create_loadbalancer( datacenter_id=datacenter_id, loadbalancer=i) self.assertEqual(response['properties']['name'], 'My LB') self.assertEqual(response['properties']['ip'], '10.2.2.3') self.assertTrue(response['properties']['dhcp']) def test_create_optional_value(self): i = LoadBalancer( name='My LB', ip='10.2.2.3', dhcp=True) response = self.loadbalancer.create_loadbalancer( datacenter_id=datacenter_id, loadbalancer=i) self.assertEqual(response['properties']['name'], 'My LB') self.assertEqual(response['properties']['ip'], '10.2.2.3') self.assertTrue(response['properties']['dhcp']) def test_get_loadbalancer_members(self): members = self.loadbalancer.get_loadbalancer_members( datacenter_id=datacenter_id, loadbalancer_id=loadbalancer_id) self.assertEqual(len(members), 4) self.assertEqual(members['items'][0]['id'], '') self.assertEqual(members['items'][0]['properties']['name'], 'nic1') self.assertEqual( members['items'][0]['properties']['mac'], 'AB:21:23:09:78:C2') def test_add_loadbalanced_nic(self): nic = '', ''] loadbalancer1 = LoadBalancer( name='My LB', balancednics=balancednics) loadbalancers = [loadbalancer1] lan1 = LAN( name='public Lan 4', public=True ) lan2 = LAN( name='public Lan 4', public=True ) lans = [lan1, lan2] d = Datacenter( name='datacenter1', description='my DC', location='de/fkb', servers=servers, volumes=volumes, loadbalancers=loadbalancers, lans=lans ) response = client.create_datacenter(datacenter=d) ## How to: Delete a Datacenter You will want to exercise a bit of caution here. Removing a datacenter will **destroy** all objects contained within that datacenter -- servers, volumes, snapshots, and so on. The objects -- once removed -- will be unrecoverable. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenter_id = '700e1cab-99b2-4c30-ba8c- datacenter = client.delete_datacenter(datacenter_id=datacenter_id) ## How to: Update Cores, Memory, and Disk ProfitBricks allows users to dynamically update cores, memory, and disk independently of each other. This removes the restriction of needing to upgrade to the next size up to receive an increase in memory. You can now simply increase the instances memory keeping your costs in-line with your resource needs. The following code illustrates how you can update cores and memory: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.update_server( datacenter_id=datacenter_id, server_id=server_id, cores=16, ram=2048) This is how you would update your volume's size: from profitbricks.client import ProfitBricksService, Volume datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' client = ProfitBricksService( username='username', password='password') volume = client.update_volume( datacenter_id=datacenter_id, volume_id=volume_id, size=100, name='Resized storage to 100 GB', cpu_hot_unplug=True) ## How to: List Servers, Volumes, and Data Centers Listing resources is fairly straight forward. Grabbing the datacenters: from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenters = client.list_datacenters() Your servers: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') servers = client.list_servers(datacenter_id=datacenter_id) Finally, your volumes: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') volumes = self.volume.list_volumes( datacenter_id=datacenter_id) ## How to: Create Additional Network Interfaces The ProfitBricks platform supports adding multiple NICs to a server. These NICs can be used to create different, segmented networks on the platform. The sample below shows you how to add a second NIC to an existing server: from profitbricks.client import ProfitBricksService, FirewallRule, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') i = NIC( name='nic1', ips=['10.2.2.3','10.2.3.4'], dhcp='true', lan=1, firewall_active=True ) response = client.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) ## Conclusion We touched on only a few ways you can interact with the ProfitBricks API using python. Our repo, located [here], has further examples. If you have any other question, ping us in the community. Keywords: profitbricks api client cloud Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Natural Language :: English Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Software Development :: Libraries :: Application Frameworks Classifier: Topic :: Internet :: WWW/HTTP profitbricks-2.3.1/profitbricks.egg-info/SOURCES.txt0000644000175000017500000000142512653761330023035 0ustar ethandethand00000000000000LICENSE MANIFEST.in README.md setup.py examples/datacenter_example.py examples/image_examples.py examples/ipblock_examples.py examples/lan_example.py examples/nic_examples.py examples/server_example.py examples/snapshot_examples.py examples/volume_example.py profitbricks/__init__.py profitbricks/client.py profitbricks.egg-info/PKG-INFO profitbricks.egg-info/SOURCES.txt profitbricks.egg-info/dependency_links.txt profitbricks.egg-info/requires.txt profitbricks.egg-info/top_level.txt tests/test_datacenter.py tests/test_firewall.py tests/test_image.py tests/test_ipblock.py tests/test_lan.py tests/test_loadbalancer.py tests/test_location.py tests/test_nic.py tests/test_profitbricks.py tests/test_provisioning_requests.py tests/test_server.py tests/test_snapshot.py tests/test_volume.pyprofitbricks-2.3.1/profitbricks.egg-info/requires.txt0000644000175000017500000000005512653761330023547 0ustar ethandethand00000000000000requests>=2.0.0 six>=1.10.0 [testing] pytestprofitbricks-2.3.1/MANIFEST.in0000664000175000017500000000011312632370277016512 0ustar ethandethand00000000000000include examples/*.py include tests/*.py include LICENSE include README.md profitbricks-2.3.1/PKG-INFO0000664000175000017500000003724012653761330016061 0ustar ethandethand00000000000000Metadata-Version: 1.1 Name: profitbricks Version: 2.3.1 Summary: ProfitBricks API Client Library for Python Home-page: https://github.com/profitbricks/profitbricks-sdk-python Author: Matt Baldwin (stackpointcloud.com) Author-email: baldwin@stackpointcloud.com License: Apache 2.0 Download-URL: https://github.com/profitbricks/profitbricks-sdk-python/tarball/2.3.1 Description: The ProfitBricks Client Library for Python provides you with access to the ProfitBricks REST API. The client library supports both simple and complex requests. It is designed for developers who are building applications in Python. This guide will walk you through getting setup with the library and performing various actions against the API. ## Table of Contents * [Concepts](#concepts) * [Getting Started](#getting-started) * [Installation](#installation) * [Authenticating](#authenticating) * [Using the Module](#using-the-module) * [Additional Documentation and Support](#additional-documentation-and-support) * [How to: Create a Datacenter](#how-to-create-a-datacenter) * [How to: Delete a Datacenter](#how-to-delete-a-datacenter) * [How to: Update Cores, Memory, and Disk](#how-to-update-cores-memory-and-disk) * [How to: List Servers, Volumes, and Data Centers](#how-to-list-servers-volumes-and-data-centers) * [How to: Create Additional Network Interfaces](#how-to-create-additional-network-interfaces) * [Conclusion](#conclusion) ## Concepts The Python Client Library wraps the latest version of the ProfitBricks REST API. All API operations are performed over SSL and authenticated using your ProfitBricks portal credentials. The API can be accessed within an instance running in ProfitBricks or directly over the Internet from any application that can send an HTTPS request and receive an HTTPS response. ## Getting Started Before you begin you will need to have [signed-up](https://www.profitbricks.com/signup) for a ProfitBricks account. The credentials you setup during sign-up will be used to authenticate against the API. ## Installation The Python Client Library is available on [PyPi](https://pypi.python.org/pypi/profitbricks). You can install the latest stable version using pip: pip install profitbricks Done! ## Authenticating Connecting to ProfitBricks is handled by first setting up your authentication. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') You can now use `client` for any future request. ## Using the Module Here are a few examples on how to use the module. In this first one we pull a list of our datacenters. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenters = client.list_datacenters() And in this one we reserve an IPBlock: from profitbricks.client import ProfitBricksService, IPBlock client = ProfitBricksService( username='username', password='password') i = IPBlock(location='de/fra', size=5) ipblock = client.reserve_ipblock(i) Some object creation supports simple and complex requests, such as a server which can be created simply by doing this: from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC, Volume datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') i = Server( name='server1', ram=4096, cores=4 ) response = client.create_server( datacenter_id=datacenter_id, server=i) or if you want one with some volumes and NICs you would do: from profitbricks.client import ProfitBricksService from profitbricks.client import Server, NIC, Volume server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, ) volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) nics = [nic1, nic2] create_volumes = [volume1, volume2] i = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=create_volumes ) response = client.create_server( datacenter_id=datacenter_id, server=i) ## Additional Documentation and Support You can find additional examples in our repo [here]. If you find any issues, please let us know via the DevOps Central community or GitHub's issue system and we'll check it out. ## How to: Create a Datacenter ProfitBricks introduces the concept of Virtual Datacenters. These are logically separated from one and the other and allow you to have a self-contained environment for all servers, volumes, networking, snapshots, and so forth. The goal is to give you the same experience as you would have if you were running your own physical datacenter. You will need a datacenter before you can create anything else. Like the server functions, the datacenter functions can be used to create a simple vDC or a complex one. To create a simple one you would do this: from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server client = ProfitBricksService( username='username', password='password') i = Datacenter( username='username', password='password', name='datacenter1', description='My New Datacenter', location='de/fkb' ) response = client.create_datacenter(datacenter=i) To create a complex datacenter you would do this. As you can see, you can create quite a few of the objects you will need later all in one request. These all get serialized in a request queue which you can check using the Requests functions: from profitbricks.client import ProfitBricksService from profitbricks.client import Datacenter, Volume, Server from profitbricks.client import LAN, NIC, LoadBalancer, FirewallRule client = ProfitBricksService( username='username', password='password') fwrule1 = FirewallRule( name='Open SSH port', protocol='TCP', source_mac='01:23:45:67:89:00', port_range_start=22 ) fwrule2 = FirewallRule( name='Allow PING', protocol='ICMP', icmp_type=8, icmp_code=0 ) fw_rules = [fwrule1, fwrule2] nic1 = NIC( name='nic1', ips=['10.2.2.3'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nic2 = NIC( name='nic2', ips=['10.2.3.4'], dhcp='true', lan=1, firewall_active=True, firewall_rules=fw_rules ) nics = [nic1, nic2] volume1 = Volume( name='volume1', size=56, image='', bus='VIRTIO' ) volume2 = Volume( name='volume2', size=56, image='', bus='VIRTIO' ) volumes = [volume2] server1 = Server( name='server1', ram=4096, cores=4, nics=nics, create_volumes=[volume1] ) servers = [server1] balancednics = ['', ''] loadbalancer1 = LoadBalancer( name='My LB', balancednics=balancednics) loadbalancers = [loadbalancer1] lan1 = LAN( name='public Lan 4', public=True ) lan2 = LAN( name='public Lan 4', public=True ) lans = [lan1, lan2] d = Datacenter( name='datacenter1', description='my DC', location='de/fkb', servers=servers, volumes=volumes, loadbalancers=loadbalancers, lans=lans ) response = client.create_datacenter(datacenter=d) ## How to: Delete a Datacenter You will want to exercise a bit of caution here. Removing a datacenter will **destroy** all objects contained within that datacenter -- servers, volumes, snapshots, and so on. The objects -- once removed -- will be unrecoverable. from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenter_id = '700e1cab-99b2-4c30-ba8c- datacenter = client.delete_datacenter(datacenter_id=datacenter_id) ## How to: Update Cores, Memory, and Disk ProfitBricks allows users to dynamically update cores, memory, and disk independently of each other. This removes the restriction of needing to upgrade to the next size up to receive an increase in memory. You can now simply increase the instances memory keeping your costs in-line with your resource needs. The following code illustrates how you can update cores and memory: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') server = client.update_server( datacenter_id=datacenter_id, server_id=server_id, cores=16, ram=2048) This is how you would update your volume's size: from profitbricks.client import ProfitBricksService, Volume datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' volume_id = '700e1cab-99b2-4c30-ba8c-1d273ddba025' client = ProfitBricksService( username='username', password='password') volume = client.update_volume( datacenter_id=datacenter_id, volume_id=volume_id, size=100, name='Resized storage to 100 GB', cpu_hot_unplug=True) ## How to: List Servers, Volumes, and Data Centers Listing resources is fairly straight forward. Grabbing the datacenters: from profitbricks.client import ProfitBricksService client = ProfitBricksService( username='username', password='password') datacenters = client.list_datacenters() Your servers: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') servers = client.list_servers(datacenter_id=datacenter_id) Finally, your volumes: from profitbricks.client import ProfitBricksService datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' client = ProfitBricksService( username='username', password='password') volumes = self.volume.list_volumes( datacenter_id=datacenter_id) ## How to: Create Additional Network Interfaces The ProfitBricks platform supports adding multiple NICs to a server. These NICs can be used to create different, segmented networks on the platform. The sample below shows you how to add a second NIC to an existing server: from profitbricks.client import ProfitBricksService, FirewallRule, NIC datacenter_id = '700e1cab-99b2-4c30-ba8c-1d273ddba022' server_id = '700e1cab-99b2-4c30-ba8c-1d273ddba023' client = ProfitBricksService( username='username', password='password') i = NIC( name='nic1', ips=['10.2.2.3','10.2.3.4'], dhcp='true', lan=1, firewall_active=True ) response = client.create_nic( datacenter_id=datacenter_id, server_id=server_id, nic=i) ## Conclusion We touched on only a few ways you can interact with the ProfitBricks API using python. Our repo, located [here], has further examples. If you have any other question, ping us in the community. Keywords: profitbricks api client cloud Platform: any Classifier: Development Status :: 5 - Production/Stable Classifier: Natural Language :: English Classifier: Environment :: Web Environment Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License Classifier: Operating System :: POSIX Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: Software Development :: Libraries :: Application Frameworks Classifier: Topic :: Internet :: WWW/HTTP